13e12c5d1SDavid du Colombier #include "u.h"
2e288d156SDavid du Colombier #include <trace.h>
3e288d156SDavid du Colombier #include "tos.h"
43e12c5d1SDavid du Colombier #include "../port/lib.h"
53e12c5d1SDavid du Colombier #include "mem.h"
63e12c5d1SDavid du Colombier #include "dat.h"
73e12c5d1SDavid du Colombier #include "fns.h"
83e12c5d1SDavid du Colombier #include "../port/error.h"
93e12c5d1SDavid du Colombier #include "ureg.h"
10696c1e60SDavid du Colombier #include "../port/edf.h"
113e12c5d1SDavid du Colombier
127dd7cddfSDavid du Colombier enum
137dd7cddfSDavid du Colombier {
147dd7cddfSDavid du Colombier Qdir,
15e288d156SDavid du Colombier Qtrace,
169a747e4fSDavid du Colombier Qargs,
179a747e4fSDavid du Colombier Qctl,
187dd7cddfSDavid du Colombier Qfd,
197dd7cddfSDavid du Colombier Qfpregs,
207dd7cddfSDavid du Colombier Qkregs,
213e12c5d1SDavid du Colombier Qmem,
223e12c5d1SDavid du Colombier Qnote,
23219b2ee8SDavid du Colombier Qnoteid,
243e12c5d1SDavid du Colombier Qnotepg,
257dd7cddfSDavid du Colombier Qns,
263e12c5d1SDavid du Colombier Qproc,
277dd7cddfSDavid du Colombier Qregs,
283e12c5d1SDavid du Colombier Qsegment,
293e12c5d1SDavid du Colombier Qstatus,
303e12c5d1SDavid du Colombier Qtext,
31219b2ee8SDavid du Colombier Qwait,
327dd7cddfSDavid du Colombier Qprofile,
33d1be6b08SDavid du Colombier Qsyscall,
343e12c5d1SDavid du Colombier };
353e12c5d1SDavid du Colombier
369a747e4fSDavid du Colombier enum
379a747e4fSDavid du Colombier {
389a747e4fSDavid du Colombier CMclose,
399a747e4fSDavid du Colombier CMclosefiles,
409a747e4fSDavid du Colombier CMfixedpri,
419a747e4fSDavid du Colombier CMhang,
429a747e4fSDavid du Colombier CMkill,
439a747e4fSDavid du Colombier CMnohang,
44b7b24591SDavid du Colombier CMnoswap,
459a747e4fSDavid du Colombier CMpri,
469a747e4fSDavid du Colombier CMprivate,
479a747e4fSDavid du Colombier CMprofile,
489a747e4fSDavid du Colombier CMstart,
499a747e4fSDavid du Colombier CMstartstop,
50e288d156SDavid du Colombier CMstartsyscall,
519a747e4fSDavid du Colombier CMstop,
529a747e4fSDavid du Colombier CMwaitstop,
539a747e4fSDavid du Colombier CMwired,
54e288d156SDavid du Colombier CMtrace,
55e288d156SDavid du Colombier /* real time */
56e288d156SDavid du Colombier CMperiod,
57e288d156SDavid du Colombier CMdeadline,
58e288d156SDavid du Colombier CMcost,
59e288d156SDavid du Colombier CMsporadic,
60e288d156SDavid du Colombier CMdeadlinenotes,
61e288d156SDavid du Colombier CMadmit,
62179dd269SDavid du Colombier CMextra,
63e288d156SDavid du Colombier CMexpel,
642cca75a1SDavid du Colombier CMevent,
65e288d156SDavid du Colombier };
66e288d156SDavid du Colombier
67e288d156SDavid du Colombier enum{
68e288d156SDavid du Colombier Nevents = 0x4000,
69e288d156SDavid du Colombier Emask = Nevents - 1,
709a747e4fSDavid du Colombier };
719a747e4fSDavid du Colombier
729a747e4fSDavid du Colombier #define STATSIZE (2*KNAMELEN+12+9*12)
739a747e4fSDavid du Colombier /*
749a747e4fSDavid du Colombier * Status, fd, and ns are left fully readable (0444) because of their use in debugging,
759a747e4fSDavid du Colombier * particularly on shared servers.
769a747e4fSDavid du Colombier * Arguably, ns and fd shouldn't be readable; if you'd prefer, change them to 0000
779a747e4fSDavid du Colombier */
783e12c5d1SDavid du Colombier Dirtab procdir[] =
793e12c5d1SDavid du Colombier {
80d9306527SDavid du Colombier "args", {Qargs}, 0, 0660,
813e12c5d1SDavid du Colombier "ctl", {Qctl}, 0, 0000,
829a747e4fSDavid du Colombier "fd", {Qfd}, 0, 0444,
837dd7cddfSDavid du Colombier "fpregs", {Qfpregs}, sizeof(FPsave), 0000,
849a747e4fSDavid du Colombier "kregs", {Qkregs}, sizeof(Ureg), 0400,
853e12c5d1SDavid du Colombier "mem", {Qmem}, 0, 0000,
863e12c5d1SDavid du Colombier "note", {Qnote}, 0, 0000,
8759cc4ca5SDavid du Colombier "noteid", {Qnoteid}, 0, 0664,
883e12c5d1SDavid du Colombier "notepg", {Qnotepg}, 0, 0000,
897dd7cddfSDavid du Colombier "ns", {Qns}, 0, 0444,
907dd7cddfSDavid du Colombier "proc", {Qproc}, 0, 0400,
917dd7cddfSDavid du Colombier "regs", {Qregs}, sizeof(Ureg), 0000,
923e12c5d1SDavid du Colombier "segment", {Qsegment}, 0, 0444,
933e12c5d1SDavid du Colombier "status", {Qstatus}, STATSIZE, 0444,
943e12c5d1SDavid du Colombier "text", {Qtext}, 0, 0000,
95219b2ee8SDavid du Colombier "wait", {Qwait}, 0, 0400,
967dd7cddfSDavid du Colombier "profile", {Qprofile}, 0, 0400,
97d1be6b08SDavid du Colombier "syscall", {Qsyscall}, 0, 0400,
983e12c5d1SDavid du Colombier };
993e12c5d1SDavid du Colombier
1009a747e4fSDavid du Colombier static
1019a747e4fSDavid du Colombier Cmdtab proccmd[] = {
1029a747e4fSDavid du Colombier CMclose, "close", 2,
1039a747e4fSDavid du Colombier CMclosefiles, "closefiles", 1,
1049a747e4fSDavid du Colombier CMfixedpri, "fixedpri", 2,
1059a747e4fSDavid du Colombier CMhang, "hang", 1,
1069a747e4fSDavid du Colombier CMnohang, "nohang", 1,
107b7b24591SDavid du Colombier CMnoswap, "noswap", 1,
1089a747e4fSDavid du Colombier CMkill, "kill", 1,
1099a747e4fSDavid du Colombier CMpri, "pri", 2,
1109a747e4fSDavid du Colombier CMprivate, "private", 1,
1119a747e4fSDavid du Colombier CMprofile, "profile", 1,
1129a747e4fSDavid du Colombier CMstart, "start", 1,
1139a747e4fSDavid du Colombier CMstartstop, "startstop", 1,
114e288d156SDavid du Colombier CMstartsyscall, "startsyscall", 1,
1159a747e4fSDavid du Colombier CMstop, "stop", 1,
1169a747e4fSDavid du Colombier CMwaitstop, "waitstop", 1,
1179a747e4fSDavid du Colombier CMwired, "wired", 2,
118179dd269SDavid du Colombier CMtrace, "trace", 0,
119e288d156SDavid du Colombier CMperiod, "period", 2,
120e288d156SDavid du Colombier CMdeadline, "deadline", 2,
121e288d156SDavid du Colombier CMcost, "cost", 2,
122e288d156SDavid du Colombier CMsporadic, "sporadic", 1,
123e288d156SDavid du Colombier CMdeadlinenotes, "deadlinenotes", 1,
124e288d156SDavid du Colombier CMadmit, "admit", 1,
125179dd269SDavid du Colombier CMextra, "extra", 1,
126e288d156SDavid du Colombier CMexpel, "expel", 1,
1272cca75a1SDavid du Colombier CMevent, "event", 1,
1289a747e4fSDavid du Colombier };
1299a747e4fSDavid du Colombier
1303e12c5d1SDavid du Colombier /* Segment type from portdat.h */
1319a747e4fSDavid du Colombier static char *sname[]={ "Text", "Data", "Bss", "Stack", "Shared", "Phys", };
1323e12c5d1SDavid du Colombier
1333e12c5d1SDavid du Colombier /*
1343e12c5d1SDavid du Colombier * Qids are, in path:
13598bee55eSDavid du Colombier * 5 bits of file type (qids above)
13698bee55eSDavid du Colombier * 26 bits of process slot number + 1
1373e12c5d1SDavid du Colombier * in vers,
1383e12c5d1SDavid du Colombier * 32 bits of pid, for consistency checking
1393e12c5d1SDavid du Colombier * If notepg, c->pgrpid.path is pgrp slot, .vers is noteid.
1403e12c5d1SDavid du Colombier */
1417dd7cddfSDavid du Colombier #define QSHIFT 5 /* location in qid of proc slot # */
1423e12c5d1SDavid du Colombier
14398bee55eSDavid du Colombier #define QID(q) ((((ulong)(q).path) & ((1<<QSHIFT)-1)) >> 0)
14498bee55eSDavid du Colombier #define SLOT(q) (((((ulong)(q).path) & ~(1UL<<31)) >> QSHIFT) - 1)
1453e12c5d1SDavid du Colombier #define PID(q) ((q).vers)
1463e12c5d1SDavid du Colombier #define NOTEID(q) ((q).vers)
1473e12c5d1SDavid du Colombier
1483e12c5d1SDavid du Colombier void procctlreq(Proc*, char*, int);
1493e12c5d1SDavid du Colombier int procctlmemio(Proc*, ulong, int, void*, int);
1503e12c5d1SDavid du Colombier Chan* proctext(Chan*, Proc*);
1513e12c5d1SDavid du Colombier Segment* txt2data(Proc*, Segment*);
1523e12c5d1SDavid du Colombier int procstopped(void*);
1537dd7cddfSDavid du Colombier void mntscan(Mntwalk*, Proc*);
1543e12c5d1SDavid du Colombier
155e288d156SDavid du Colombier static Traceevent *tevents;
156e288d156SDavid du Colombier static Lock tlock;
157e288d156SDavid du Colombier static int topens;
158e288d156SDavid du Colombier static int tproduced, tconsumed;
1590701b922SDavid du Colombier void (*proctrace)(Proc*, int, vlong);
160e288d156SDavid du Colombier
161a6a9e072SDavid du Colombier extern int unfair;
162a6a9e072SDavid du Colombier
163e288d156SDavid du Colombier static void
profclock(Ureg * ur,Timer *)164e288d156SDavid du Colombier profclock(Ureg *ur, Timer *)
165e288d156SDavid du Colombier {
166e288d156SDavid du Colombier Tos *tos;
167e288d156SDavid du Colombier
168e288d156SDavid du Colombier if(up == 0 || up->state != Running)
169e288d156SDavid du Colombier return;
170e288d156SDavid du Colombier
171e288d156SDavid du Colombier /* user profiling clock */
172e288d156SDavid du Colombier if(userureg(ur)){
173e288d156SDavid du Colombier tos = (Tos*)(USTKTOP-sizeof(Tos));
174e288d156SDavid du Colombier tos->clock += TK2MS(1);
175e288d156SDavid du Colombier segclock(ur->pc);
176e288d156SDavid du Colombier }
177e288d156SDavid du Colombier }
178e288d156SDavid du Colombier
1797dd7cddfSDavid du Colombier static int
procgen(Chan * c,char * name,Dirtab * tab,int,int s,Dir * dp)1809a747e4fSDavid du Colombier procgen(Chan *c, char *name, Dirtab *tab, int, int s, Dir *dp)
1813e12c5d1SDavid du Colombier {
1823e12c5d1SDavid du Colombier Qid qid;
1833e12c5d1SDavid du Colombier Proc *p;
1849a747e4fSDavid du Colombier char *ename;
1857dd7cddfSDavid du Colombier Segment *q;
186219b2ee8SDavid du Colombier ulong pid, path, perm, len;
1873e12c5d1SDavid du Colombier
1887dd7cddfSDavid du Colombier if(s == DEVDOTDOT){
1899a747e4fSDavid du Colombier mkqid(&qid, Qdir, 0, QTDIR);
1909a747e4fSDavid du Colombier devdir(c, qid, "#p", 0, eve, 0555, dp);
1917dd7cddfSDavid du Colombier return 1;
1927dd7cddfSDavid du Colombier }
1937dd7cddfSDavid du Colombier
1949a747e4fSDavid du Colombier if(c->qid.path == Qdir){
195e288d156SDavid du Colombier if(s == 0){
196e288d156SDavid du Colombier strcpy(up->genbuf, "trace");
197e288d156SDavid du Colombier mkqid(&qid, Qtrace, -1, QTFILE);
198e288d156SDavid du Colombier devdir(c, qid, up->genbuf, 0, eve, 0444, dp);
199e288d156SDavid du Colombier return 1;
200e288d156SDavid du Colombier }
201e288d156SDavid du Colombier
2029a747e4fSDavid du Colombier if(name != nil){
2039a747e4fSDavid du Colombier /* ignore s and use name to find pid */
2049a747e4fSDavid du Colombier pid = strtol(name, &ename, 10);
2059a747e4fSDavid du Colombier if(pid==0 || ename[0]!='\0')
2069a747e4fSDavid du Colombier return -1;
2079a747e4fSDavid du Colombier s = procindex(pid);
2089a747e4fSDavid du Colombier if(s < 0)
2099a747e4fSDavid du Colombier return -1;
210e288d156SDavid du Colombier }
211e288d156SDavid du Colombier else if(--s >= conf.nproc)
2123e12c5d1SDavid du Colombier return -1;
213e288d156SDavid du Colombier
2143e12c5d1SDavid du Colombier p = proctab(s);
2153e12c5d1SDavid du Colombier pid = p->pid;
2163e12c5d1SDavid du Colombier if(pid == 0)
2173e12c5d1SDavid du Colombier return 0;
218*4e3613abSDavid du Colombier snprint(up->genbuf, sizeof up->genbuf, "%lud", pid);
2199a747e4fSDavid du Colombier /*
2209a747e4fSDavid du Colombier * String comparison is done in devwalk so name must match its formatted pid
2219a747e4fSDavid du Colombier */
2229a747e4fSDavid du Colombier if(name != nil && strcmp(name, up->genbuf) != 0)
2239a747e4fSDavid du Colombier return -1;
2249a747e4fSDavid du Colombier mkqid(&qid, (s+1)<<QSHIFT, pid, QTDIR);
2259a747e4fSDavid du Colombier devdir(c, qid, up->genbuf, 0, p->user, DMDIR|0555, dp);
2263e12c5d1SDavid du Colombier return 1;
2273e12c5d1SDavid du Colombier }
228e288d156SDavid du Colombier if(c->qid.path == Qtrace){
229e288d156SDavid du Colombier strcpy(up->genbuf, "trace");
230e288d156SDavid du Colombier mkqid(&qid, Qtrace, -1, QTFILE);
231e288d156SDavid du Colombier devdir(c, qid, up->genbuf, 0, eve, 0444, dp);
232e288d156SDavid du Colombier return 1;
233e288d156SDavid du Colombier }
234c957ad6aSDavid du Colombier if(s >= nelem(procdir))
2353e12c5d1SDavid du Colombier return -1;
2363e12c5d1SDavid du Colombier if(tab)
2373e12c5d1SDavid du Colombier panic("procgen");
2383e12c5d1SDavid du Colombier
2393e12c5d1SDavid du Colombier tab = &procdir[s];
2409a747e4fSDavid du Colombier path = c->qid.path&~(((1<<QSHIFT)-1)); /* slot component */
2413e12c5d1SDavid du Colombier
242717772fdSDavid du Colombier /* p->procmode determines default mode for files in /proc */
2433e12c5d1SDavid du Colombier p = proctab(SLOT(c->qid));
2443e12c5d1SDavid du Colombier perm = tab->perm;
2453e12c5d1SDavid du Colombier if(perm == 0)
2463e12c5d1SDavid du Colombier perm = p->procmode;
24759cc4ca5SDavid du Colombier else /* just copy read bits */
24859cc4ca5SDavid du Colombier perm |= p->procmode & 0444;
2493e12c5d1SDavid du Colombier
250219b2ee8SDavid du Colombier len = tab->length;
2517dd7cddfSDavid du Colombier switch(QID(c->qid)) {
2527dd7cddfSDavid du Colombier case Qwait:
2539a747e4fSDavid du Colombier len = p->nwait; /* incorrect size, but >0 means there's something to read */
2547dd7cddfSDavid du Colombier break;
2557dd7cddfSDavid du Colombier case Qprofile:
2567dd7cddfSDavid du Colombier q = p->seg[TSEG];
2577dd7cddfSDavid du Colombier if(q && q->profile) {
2587dd7cddfSDavid du Colombier len = (q->top-q->base)>>LRESPROF;
2597dd7cddfSDavid du Colombier len *= sizeof(*q->profile);
2607dd7cddfSDavid du Colombier }
2617dd7cddfSDavid du Colombier break;
2627dd7cddfSDavid du Colombier }
263219b2ee8SDavid du Colombier
2649a747e4fSDavid du Colombier mkqid(&qid, path|tab->qid.path, c->qid.vers, QTFILE);
265219b2ee8SDavid du Colombier devdir(c, qid, tab->name, len, p->user, perm, dp);
2663e12c5d1SDavid du Colombier return 1;
2673e12c5d1SDavid du Colombier }
2683e12c5d1SDavid du Colombier
2697dd7cddfSDavid du Colombier static void
_proctrace(Proc * p,Tevent etype,vlong ts)2700701b922SDavid du Colombier _proctrace(Proc* p, Tevent etype, vlong ts)
271e288d156SDavid du Colombier {
272e288d156SDavid du Colombier Traceevent *te;
273e288d156SDavid du Colombier
274da51d93aSDavid du Colombier if (p->trace == 0 || topens == 0 ||
275da51d93aSDavid du Colombier tproduced - tconsumed >= Nevents)
276e288d156SDavid du Colombier return;
277e288d156SDavid du Colombier
278e288d156SDavid du Colombier te = &tevents[tproduced&Emask];
279e288d156SDavid du Colombier te->pid = p->pid;
280e288d156SDavid du Colombier te->etype = etype;
2810701b922SDavid du Colombier if (ts == 0)
282e288d156SDavid du Colombier te->time = todget(nil);
2830701b922SDavid du Colombier else
2840701b922SDavid du Colombier te->time = ts;
285e288d156SDavid du Colombier tproduced++;
286e288d156SDavid du Colombier }
287e288d156SDavid du Colombier
288e288d156SDavid du Colombier static void
procinit(void)2893e12c5d1SDavid du Colombier procinit(void)
2903e12c5d1SDavid du Colombier {
29198bee55eSDavid du Colombier if(conf.nproc >= (1<<(31-QSHIFT))-1)
2923e12c5d1SDavid du Colombier print("warning: too many procs for devproc\n");
293e288d156SDavid du Colombier addclock0link((void (*)(void))profclock, 113); /* Relative prime to HZ */
2943e12c5d1SDavid du Colombier }
2953e12c5d1SDavid du Colombier
2967dd7cddfSDavid du Colombier static Chan*
procattach(char * spec)2973e12c5d1SDavid du Colombier procattach(char *spec)
2983e12c5d1SDavid du Colombier {
2993e12c5d1SDavid du Colombier return devattach('p', spec);
3003e12c5d1SDavid du Colombier }
3013e12c5d1SDavid du Colombier
3029a747e4fSDavid du Colombier static Walkqid*
procwalk(Chan * c,Chan * nc,char ** name,int nname)3039a747e4fSDavid du Colombier procwalk(Chan *c, Chan *nc, char **name, int nname)
3043e12c5d1SDavid du Colombier {
3059a747e4fSDavid du Colombier return devwalk(c, nc, name, nname, 0, 0, procgen);
3063e12c5d1SDavid du Colombier }
3073e12c5d1SDavid du Colombier
3089a747e4fSDavid du Colombier static int
procstat(Chan * c,uchar * db,int n)3099a747e4fSDavid du Colombier procstat(Chan *c, uchar *db, int n)
3103e12c5d1SDavid du Colombier {
3119a747e4fSDavid du Colombier return devstat(c, db, n, 0, 0, procgen);
3129a747e4fSDavid du Colombier }
3139a747e4fSDavid du Colombier
3149a747e4fSDavid du Colombier /*
3159a747e4fSDavid du Colombier * none can't read or write state on other
3169a747e4fSDavid du Colombier * processes. This is to contain access of
3179a747e4fSDavid du Colombier * servers running as none should they be
3189a747e4fSDavid du Colombier * subverted by, for example, a stack attack.
3199a747e4fSDavid du Colombier */
3209a747e4fSDavid du Colombier static void
nonone(Proc * p)3219a747e4fSDavid du Colombier nonone(Proc *p)
3229a747e4fSDavid du Colombier {
3239a747e4fSDavid du Colombier if(p == up)
3249a747e4fSDavid du Colombier return;
3259a747e4fSDavid du Colombier if(strcmp(up->user, "none") != 0)
3269a747e4fSDavid du Colombier return;
3279a747e4fSDavid du Colombier if(iseve())
3289a747e4fSDavid du Colombier return;
3299a747e4fSDavid du Colombier error(Eperm);
3303e12c5d1SDavid du Colombier }
3313e12c5d1SDavid du Colombier
3327dd7cddfSDavid du Colombier static Chan*
procopen(Chan * c,int omode)3333e12c5d1SDavid du Colombier procopen(Chan *c, int omode)
3343e12c5d1SDavid du Colombier {
3353e12c5d1SDavid du Colombier Proc *p;
3363e12c5d1SDavid du Colombier Pgrp *pg;
3373e12c5d1SDavid du Colombier Chan *tc;
3387dd7cddfSDavid du Colombier int pid;
3393e12c5d1SDavid du Colombier
3409a747e4fSDavid du Colombier if(c->qid.type & QTDIR)
3413e12c5d1SDavid du Colombier return devopen(c, omode, 0, 0, procgen);
3423e12c5d1SDavid du Colombier
343e288d156SDavid du Colombier if(QID(c->qid) == Qtrace){
344e288d156SDavid du Colombier if (omode != OREAD)
345e288d156SDavid du Colombier error(Eperm);
346e288d156SDavid du Colombier lock(&tlock);
347e288d156SDavid du Colombier if (waserror()){
348e288d156SDavid du Colombier unlock(&tlock);
349e288d156SDavid du Colombier nexterror();
350e288d156SDavid du Colombier }
351e288d156SDavid du Colombier if (topens > 0)
352e288d156SDavid du Colombier error("already open");
353e288d156SDavid du Colombier topens++;
354e288d156SDavid du Colombier if (tevents == nil){
355e288d156SDavid du Colombier tevents = (Traceevent*)malloc(sizeof(Traceevent) * Nevents);
356e288d156SDavid du Colombier if(tevents == nil)
357e288d156SDavid du Colombier error(Enomem);
358e288d156SDavid du Colombier tproduced = tconsumed = 0;
359e288d156SDavid du Colombier }
360e288d156SDavid du Colombier proctrace = _proctrace;
361e288d156SDavid du Colombier unlock(&tlock);
362e288d156SDavid du Colombier poperror();
363e288d156SDavid du Colombier
364e288d156SDavid du Colombier c->mode = openmode(omode);
365e288d156SDavid du Colombier c->flag |= COPEN;
366e288d156SDavid du Colombier c->offset = 0;
367e288d156SDavid du Colombier return c;
368e288d156SDavid du Colombier }
369e288d156SDavid du Colombier
3703e12c5d1SDavid du Colombier p = proctab(SLOT(c->qid));
3717dd7cddfSDavid du Colombier qlock(&p->debug);
3727dd7cddfSDavid du Colombier if(waserror()){
3737dd7cddfSDavid du Colombier qunlock(&p->debug);
3747dd7cddfSDavid du Colombier nexterror();
3757dd7cddfSDavid du Colombier }
3767dd7cddfSDavid du Colombier pid = PID(c->qid);
3777dd7cddfSDavid du Colombier if(p->pid != pid)
3783e12c5d1SDavid du Colombier error(Eprocdied);
3793e12c5d1SDavid du Colombier
3803e12c5d1SDavid du Colombier omode = openmode(omode);
3813e12c5d1SDavid du Colombier
3823e12c5d1SDavid du Colombier switch(QID(c->qid)){
3833e12c5d1SDavid du Colombier case Qtext:
3847dd7cddfSDavid du Colombier if(omode != OREAD)
3857dd7cddfSDavid du Colombier error(Eperm);
3863e12c5d1SDavid du Colombier tc = proctext(c, p);
3873e12c5d1SDavid du Colombier tc->offset = 0;
3887dd7cddfSDavid du Colombier qunlock(&p->debug);
3897dd7cddfSDavid du Colombier poperror();
39009474398SDavid du Colombier cclose(c);
3913e12c5d1SDavid du Colombier return tc;
3923e12c5d1SDavid du Colombier
3937dd7cddfSDavid du Colombier case Qproc:
3947dd7cddfSDavid du Colombier case Qkregs:
3957dd7cddfSDavid du Colombier case Qsegment:
3967dd7cddfSDavid du Colombier case Qprofile:
3977dd7cddfSDavid du Colombier case Qfd:
3987dd7cddfSDavid du Colombier if(omode != OREAD)
3997dd7cddfSDavid du Colombier error(Eperm);
4007dd7cddfSDavid du Colombier break;
4017dd7cddfSDavid du Colombier
4029a747e4fSDavid du Colombier case Qnote:
403da51d93aSDavid du Colombier if(p->privatemem)
404da51d93aSDavid du Colombier error(Eperm);
405da51d93aSDavid du Colombier break;
406da51d93aSDavid du Colombier
407da51d93aSDavid du Colombier case Qmem:
4089a747e4fSDavid du Colombier case Qctl:
4099a747e4fSDavid du Colombier if(p->privatemem)
4109a747e4fSDavid du Colombier error(Eperm);
411da51d93aSDavid du Colombier nonone(p);
412da51d93aSDavid du Colombier break;
413da51d93aSDavid du Colombier
4149a747e4fSDavid du Colombier case Qargs:
4159a747e4fSDavid du Colombier case Qnoteid:
4163e12c5d1SDavid du Colombier case Qstatus:
417219b2ee8SDavid du Colombier case Qwait:
4187dd7cddfSDavid du Colombier case Qregs:
4197dd7cddfSDavid du Colombier case Qfpregs:
420d1be6b08SDavid du Colombier case Qsyscall:
4219a747e4fSDavid du Colombier nonone(p);
4227dd7cddfSDavid du Colombier break;
4237dd7cddfSDavid du Colombier
4247dd7cddfSDavid du Colombier case Qns:
4257dd7cddfSDavid du Colombier if(omode != OREAD)
4267dd7cddfSDavid du Colombier error(Eperm);
4277dd7cddfSDavid du Colombier c->aux = malloc(sizeof(Mntwalk));
4283e12c5d1SDavid du Colombier break;
4293e12c5d1SDavid du Colombier
4303e12c5d1SDavid du Colombier case Qnotepg:
4319a747e4fSDavid du Colombier nonone(p);
4327dd7cddfSDavid du Colombier pg = p->pgrp;
4337dd7cddfSDavid du Colombier if(pg == nil)
4347dd7cddfSDavid du Colombier error(Eprocdied);
4353e12c5d1SDavid du Colombier if(omode!=OWRITE || pg->pgrpid == 1)
4363e12c5d1SDavid du Colombier error(Eperm);
4373e12c5d1SDavid du Colombier c->pgrpid.path = pg->pgrpid+1;
4383e12c5d1SDavid du Colombier c->pgrpid.vers = p->noteid;
4393e12c5d1SDavid du Colombier break;
4403e12c5d1SDavid du Colombier
4413e12c5d1SDavid du Colombier default:
442e464ed1aSDavid du Colombier pprint("procopen %#lux\n", QID(c->qid));
4433e12c5d1SDavid du Colombier error(Egreg);
4443e12c5d1SDavid du Colombier }
4453e12c5d1SDavid du Colombier
4463e12c5d1SDavid du Colombier /* Affix pid to qid */
4473e12c5d1SDavid du Colombier if(p->state != Dead)
4483e12c5d1SDavid du Colombier c->qid.vers = p->pid;
4493e12c5d1SDavid du Colombier
4507dd7cddfSDavid du Colombier /* make sure the process slot didn't get reallocated while we were playing */
4517dd7cddfSDavid du Colombier coherence();
4527dd7cddfSDavid du Colombier if(p->pid != pid)
4537dd7cddfSDavid du Colombier error(Eprocdied);
4547dd7cddfSDavid du Colombier
4557dd7cddfSDavid du Colombier tc = devopen(c, omode, 0, 0, procgen);
4567dd7cddfSDavid du Colombier qunlock(&p->debug);
4577dd7cddfSDavid du Colombier poperror();
4587dd7cddfSDavid du Colombier
4597dd7cddfSDavid du Colombier return tc;
4603e12c5d1SDavid du Colombier }
4613e12c5d1SDavid du Colombier
4629a747e4fSDavid du Colombier static int
procwstat(Chan * c,uchar * db,int n)4639a747e4fSDavid du Colombier procwstat(Chan *c, uchar *db, int n)
4643e12c5d1SDavid du Colombier {
4653e12c5d1SDavid du Colombier Proc *p;
4669a747e4fSDavid du Colombier Dir *d;
4673e12c5d1SDavid du Colombier
4689a747e4fSDavid du Colombier if(c->qid.type&QTDIR)
4693e12c5d1SDavid du Colombier error(Eperm);
4703e12c5d1SDavid du Colombier
471e288d156SDavid du Colombier if(QID(c->qid) == Qtrace)
472e288d156SDavid du Colombier return devwstat(c, db, n);
473e288d156SDavid du Colombier
4743e12c5d1SDavid du Colombier p = proctab(SLOT(c->qid));
4759a747e4fSDavid du Colombier nonone(p);
4769a747e4fSDavid du Colombier d = nil;
4777dd7cddfSDavid du Colombier if(waserror()){
4789a747e4fSDavid du Colombier free(d);
4797dd7cddfSDavid du Colombier qunlock(&p->debug);
4807dd7cddfSDavid du Colombier nexterror();
4817dd7cddfSDavid du Colombier }
4827dd7cddfSDavid du Colombier qlock(&p->debug);
4837dd7cddfSDavid du Colombier
4843e12c5d1SDavid du Colombier if(p->pid != PID(c->qid))
4853e12c5d1SDavid du Colombier error(Eprocdied);
4863e12c5d1SDavid du Colombier
4877dd7cddfSDavid du Colombier if(strcmp(up->user, p->user) != 0 && strcmp(up->user, eve) != 0)
4883e12c5d1SDavid du Colombier error(Eperm);
4893e12c5d1SDavid du Colombier
4909a747e4fSDavid du Colombier d = smalloc(sizeof(Dir)+n);
4919a747e4fSDavid du Colombier n = convM2D(db, n, &d[0], (char*)&d[1]);
4929a747e4fSDavid du Colombier if(n == 0)
4939a747e4fSDavid du Colombier error(Eshortstat);
4949a747e4fSDavid du Colombier if(!emptystr(d->uid) && strcmp(d->uid, p->user) != 0){
4957dd7cddfSDavid du Colombier if(strcmp(up->user, eve) != 0)
4967dd7cddfSDavid du Colombier error(Eperm);
4979a747e4fSDavid du Colombier else
4989a747e4fSDavid du Colombier kstrdup(&p->user, d->uid);
4997dd7cddfSDavid du Colombier }
500717772fdSDavid du Colombier /* p->procmode determines default mode for files in /proc */
5019a747e4fSDavid du Colombier if(d->mode != ~0UL)
5029a747e4fSDavid du Colombier p->procmode = d->mode&0777;
5037dd7cddfSDavid du Colombier
5047dd7cddfSDavid du Colombier poperror();
5059a747e4fSDavid du Colombier free(d);
5067dd7cddfSDavid du Colombier qunlock(&p->debug);
5079a747e4fSDavid du Colombier return n;
5083e12c5d1SDavid du Colombier }
5093e12c5d1SDavid du Colombier
5109a747e4fSDavid du Colombier
51180ee5cbfSDavid du Colombier static long
procoffset(long offset,char * va,int * np)51280ee5cbfSDavid du Colombier procoffset(long offset, char *va, int *np)
51380ee5cbfSDavid du Colombier {
51480ee5cbfSDavid du Colombier if(offset > 0) {
51580ee5cbfSDavid du Colombier offset -= *np;
51680ee5cbfSDavid du Colombier if(offset < 0) {
51780ee5cbfSDavid du Colombier memmove(va, va+*np+offset, -offset);
51880ee5cbfSDavid du Colombier *np = -offset;
51980ee5cbfSDavid du Colombier }
52080ee5cbfSDavid du Colombier else
52180ee5cbfSDavid du Colombier *np = 0;
52280ee5cbfSDavid du Colombier }
52380ee5cbfSDavid du Colombier return offset;
52480ee5cbfSDavid du Colombier }
52580ee5cbfSDavid du Colombier
5267dd7cddfSDavid du Colombier static int
procqidwidth(Chan * c)5279a747e4fSDavid du Colombier procqidwidth(Chan *c)
5289a747e4fSDavid du Colombier {
5299a747e4fSDavid du Colombier char buf[32];
5309a747e4fSDavid du Colombier
531*4e3613abSDavid du Colombier return snprint(buf, sizeof buf, "%lud", c->qid.vers);
5329a747e4fSDavid du Colombier }
5339a747e4fSDavid du Colombier
5349a747e4fSDavid du Colombier int
procfdprint(Chan * c,int fd,int w,char * s,int ns)5359a747e4fSDavid du Colombier procfdprint(Chan *c, int fd, int w, char *s, int ns)
5369a747e4fSDavid du Colombier {
5379a747e4fSDavid du Colombier int n;
5389a747e4fSDavid du Colombier
5399a747e4fSDavid du Colombier if(w == 0)
5409a747e4fSDavid du Colombier w = procqidwidth(c);
5419a747e4fSDavid du Colombier n = snprint(s, ns, "%3d %.2s %C %4ld (%.16llux %*lud %.2ux) %5ld %8lld %s\n",
5429a747e4fSDavid du Colombier fd,
5439a747e4fSDavid du Colombier &"r w rw"[(c->mode&3)<<1],
5449a747e4fSDavid du Colombier devtab[c->type]->dc, c->dev,
5459a747e4fSDavid du Colombier c->qid.path, w, c->qid.vers, c->qid.type,
5464afe124fSDavid du Colombier c->iounit, c->offset, c->path->s);
5479a747e4fSDavid du Colombier return n;
5489a747e4fSDavid du Colombier }
5499a747e4fSDavid du Colombier
5509a747e4fSDavid du Colombier static int
procfds(Proc * p,char * va,int count,long offset)5517dd7cddfSDavid du Colombier procfds(Proc *p, char *va, int count, long offset)
5527dd7cddfSDavid du Colombier {
5537dd7cddfSDavid du Colombier Fgrp *f;
5547dd7cddfSDavid du Colombier Chan *c;
5559a747e4fSDavid du Colombier char buf[256];
5569a747e4fSDavid du Colombier int n, i, w, ww;
5579a747e4fSDavid du Colombier char *a;
5589a747e4fSDavid du Colombier
5599a747e4fSDavid du Colombier /* print to buf to avoid holding fgrp lock while writing to user space */
5609a747e4fSDavid du Colombier if(count > sizeof buf)
5619a747e4fSDavid du Colombier count = sizeof buf;
5629a747e4fSDavid du Colombier a = buf;
5637dd7cddfSDavid du Colombier
5647dd7cddfSDavid du Colombier qlock(&p->debug);
5657dd7cddfSDavid du Colombier f = p->fgrp;
5667dd7cddfSDavid du Colombier if(f == nil){
5677dd7cddfSDavid du Colombier qunlock(&p->debug);
5687dd7cddfSDavid du Colombier return 0;
5697dd7cddfSDavid du Colombier }
5707dd7cddfSDavid du Colombier lock(f);
5717dd7cddfSDavid du Colombier if(waserror()){
5727dd7cddfSDavid du Colombier unlock(f);
5737dd7cddfSDavid du Colombier qunlock(&p->debug);
5747dd7cddfSDavid du Colombier nexterror();
5757dd7cddfSDavid du Colombier }
5767dd7cddfSDavid du Colombier
5774afe124fSDavid du Colombier n = readstr(0, a, count, p->dot->path->s);
5789a747e4fSDavid du Colombier n += snprint(a+n, count-n, "\n");
5799a747e4fSDavid du Colombier offset = procoffset(offset, a, &n);
5809a747e4fSDavid du Colombier /* compute width of qid.path */
5819a747e4fSDavid du Colombier w = 0;
5827dd7cddfSDavid du Colombier for(i = 0; i <= f->maxfd; i++) {
5837dd7cddfSDavid du Colombier c = f->fd[i];
5847dd7cddfSDavid du Colombier if(c == nil)
5857dd7cddfSDavid du Colombier continue;
5869a747e4fSDavid du Colombier ww = procqidwidth(c);
5879a747e4fSDavid du Colombier if(ww > w)
5889a747e4fSDavid du Colombier w = ww;
5899a747e4fSDavid du Colombier }
5909a747e4fSDavid du Colombier for(i = 0; i <= f->maxfd; i++) {
5919a747e4fSDavid du Colombier c = f->fd[i];
5929a747e4fSDavid du Colombier if(c == nil)
5939a747e4fSDavid du Colombier continue;
5949a747e4fSDavid du Colombier n += procfdprint(c, i, w, a+n, count-n);
5959a747e4fSDavid du Colombier offset = procoffset(offset, a, &n);
5967dd7cddfSDavid du Colombier }
5977dd7cddfSDavid du Colombier unlock(f);
5987dd7cddfSDavid du Colombier qunlock(&p->debug);
5997dd7cddfSDavid du Colombier poperror();
6007dd7cddfSDavid du Colombier
6019a747e4fSDavid du Colombier /* copy result to user space, now that locks are released */
6029a747e4fSDavid du Colombier memmove(va, buf, n);
6039a747e4fSDavid du Colombier
6047dd7cddfSDavid du Colombier return n;
6057dd7cddfSDavid du Colombier }
6067dd7cddfSDavid du Colombier
6077dd7cddfSDavid du Colombier static void
procclose(Chan * c)6083e12c5d1SDavid du Colombier procclose(Chan * c)
6093e12c5d1SDavid du Colombier {
610e288d156SDavid du Colombier if(QID(c->qid) == Qtrace){
611e288d156SDavid du Colombier lock(&tlock);
612e288d156SDavid du Colombier if(topens > 0)
613e288d156SDavid du Colombier topens--;
614e288d156SDavid du Colombier if(topens == 0)
615e288d156SDavid du Colombier proctrace = nil;
616e288d156SDavid du Colombier unlock(&tlock);
617e288d156SDavid du Colombier }
6187dd7cddfSDavid du Colombier if(QID(c->qid) == Qns && c->aux != 0)
6197dd7cddfSDavid du Colombier free(c->aux);
6203e12c5d1SDavid du Colombier }
6213e12c5d1SDavid du Colombier
6227dd7cddfSDavid du Colombier static void
int2flag(int flag,char * s)6237dd7cddfSDavid du Colombier int2flag(int flag, char *s)
6243e12c5d1SDavid du Colombier {
6257dd7cddfSDavid du Colombier if(flag == 0){
6267dd7cddfSDavid du Colombier *s = '\0';
6277dd7cddfSDavid du Colombier return;
6287dd7cddfSDavid du Colombier }
6297dd7cddfSDavid du Colombier *s++ = '-';
6307dd7cddfSDavid du Colombier if(flag & MAFTER)
6317dd7cddfSDavid du Colombier *s++ = 'a';
6327dd7cddfSDavid du Colombier if(flag & MBEFORE)
6337dd7cddfSDavid du Colombier *s++ = 'b';
6347dd7cddfSDavid du Colombier if(flag & MCREATE)
6357dd7cddfSDavid du Colombier *s++ = 'c';
6367dd7cddfSDavid du Colombier if(flag & MCACHE)
6377dd7cddfSDavid du Colombier *s++ = 'C';
6387dd7cddfSDavid du Colombier *s = '\0';
6397dd7cddfSDavid du Colombier }
6407dd7cddfSDavid du Colombier
6419a747e4fSDavid du Colombier static int
procargs(Proc * p,char * buf,int nbuf)6429a747e4fSDavid du Colombier procargs(Proc *p, char *buf, int nbuf)
6439a747e4fSDavid du Colombier {
6449a747e4fSDavid du Colombier int j, k, m;
6459a747e4fSDavid du Colombier char *a;
6469a747e4fSDavid du Colombier int n;
6479a747e4fSDavid du Colombier
6489a747e4fSDavid du Colombier a = p->args;
649d9306527SDavid du Colombier if(p->setargs){
650d9306527SDavid du Colombier snprint(buf, nbuf, "%s [%s]", p->text, p->args);
651d9306527SDavid du Colombier return strlen(buf);
652d9306527SDavid du Colombier }
6539a747e4fSDavid du Colombier n = p->nargs;
6549a747e4fSDavid du Colombier for(j = 0; j < nbuf - 1; j += m){
655d9306527SDavid du Colombier if(n <= 0)
6569a747e4fSDavid du Colombier break;
6579a747e4fSDavid du Colombier if(j != 0)
6589a747e4fSDavid du Colombier buf[j++] = ' ';
6599a747e4fSDavid du Colombier m = snprint(buf+j, nbuf-j, "%q", a);
6609a747e4fSDavid du Colombier k = strlen(a) + 1;
6619a747e4fSDavid du Colombier a += k;
6629a747e4fSDavid du Colombier n -= k;
6639a747e4fSDavid du Colombier }
6649a747e4fSDavid du Colombier return j;
6659a747e4fSDavid du Colombier }
6669a747e4fSDavid du Colombier
667e288d156SDavid du Colombier static int
eventsavailable(void *)668e288d156SDavid du Colombier eventsavailable(void *)
669e288d156SDavid du Colombier {
670e288d156SDavid du Colombier return tproduced > tconsumed;
671e288d156SDavid du Colombier }
672e288d156SDavid du Colombier
6737dd7cddfSDavid du Colombier static long
procread(Chan * c,void * va,long n,vlong off)6747dd7cddfSDavid du Colombier procread(Chan *c, void *va, long n, vlong off)
6757dd7cddfSDavid du Colombier {
676208510e1SDavid du Colombier /* NSEG*32 was too small for worst cases */
677208510e1SDavid du Colombier char *a, flag[10], *sps, *srv, statbuf[NSEG*64];
6784de34a7eSDavid du Colombier int i, j, m, navail, ne, pid, rsize;
6793e12c5d1SDavid du Colombier long l;
6807dd7cddfSDavid du Colombier uchar *rptr;
6814de34a7eSDavid du Colombier ulong offset;
6824de34a7eSDavid du Colombier Confmem *cm;
6837dd7cddfSDavid du Colombier Mntwalk *mw;
6844de34a7eSDavid du Colombier Proc *p;
6857dd7cddfSDavid du Colombier Segment *sg, *s;
6864de34a7eSDavid du Colombier Ureg kur;
6874de34a7eSDavid du Colombier Waitq *wq;
6884de34a7eSDavid du Colombier
6894de34a7eSDavid du Colombier a = va;
6904de34a7eSDavid du Colombier offset = off;
6913e12c5d1SDavid du Colombier
6929a747e4fSDavid du Colombier if(c->qid.type & QTDIR)
6933e12c5d1SDavid du Colombier return devdirread(c, a, n, 0, 0, procgen);
6943e12c5d1SDavid du Colombier
695e288d156SDavid du Colombier if(QID(c->qid) == Qtrace){
696e288d156SDavid du Colombier if(!eventsavailable(nil))
697e288d156SDavid du Colombier return 0;
698e288d156SDavid du Colombier
699e288d156SDavid du Colombier rptr = (uchar*)va;
700e288d156SDavid du Colombier navail = tproduced - tconsumed;
701e288d156SDavid du Colombier if(navail > n / sizeof(Traceevent))
702e288d156SDavid du Colombier navail = n / sizeof(Traceevent);
703e288d156SDavid du Colombier while(navail > 0) {
704e288d156SDavid du Colombier ne = ((tconsumed & Emask) + navail > Nevents)?
705e288d156SDavid du Colombier Nevents - (tconsumed & Emask): navail;
706e288d156SDavid du Colombier memmove(rptr, &tevents[tconsumed & Emask],
707e288d156SDavid du Colombier ne * sizeof(Traceevent));
708e288d156SDavid du Colombier
709e288d156SDavid du Colombier tconsumed += ne;
710e288d156SDavid du Colombier rptr += ne * sizeof(Traceevent);
711e288d156SDavid du Colombier navail -= ne;
712e288d156SDavid du Colombier }
713e288d156SDavid du Colombier return rptr - (uchar*)va;
714e288d156SDavid du Colombier }
715e288d156SDavid du Colombier
7163e12c5d1SDavid du Colombier p = proctab(SLOT(c->qid));
7173e12c5d1SDavid du Colombier if(p->pid != PID(c->qid))
7183e12c5d1SDavid du Colombier error(Eprocdied);
7193e12c5d1SDavid du Colombier
7203e12c5d1SDavid du Colombier switch(QID(c->qid)){
7219a747e4fSDavid du Colombier case Qargs:
722d9306527SDavid du Colombier qlock(&p->debug);
723cdf9e71cSDavid du Colombier j = procargs(p, up->genbuf, sizeof up->genbuf);
724d9306527SDavid du Colombier qunlock(&p->debug);
7259a747e4fSDavid du Colombier if(offset >= j)
7269a747e4fSDavid du Colombier return 0;
7279a747e4fSDavid du Colombier if(offset+n > j)
7289a747e4fSDavid du Colombier n = j-offset;
729cdf9e71cSDavid du Colombier memmove(a, &up->genbuf[offset], n);
7309a747e4fSDavid du Colombier return n;
731d1be6b08SDavid du Colombier case Qsyscall:
732d1be6b08SDavid du Colombier if(!p->syscalltrace)
733d1be6b08SDavid du Colombier return 0;
734d1be6b08SDavid du Colombier n = readstr(offset, a, n, p->syscalltrace);
735d1be6b08SDavid du Colombier return n;
7369a747e4fSDavid du Colombier
7373e12c5d1SDavid du Colombier case Qmem:
7384de34a7eSDavid du Colombier if(offset < KZERO)
7397dd7cddfSDavid du Colombier return procctlmemio(p, offset, n, va, 1);
7403e12c5d1SDavid du Colombier
741b7b24591SDavid du Colombier if(!iseve())
742b7b24591SDavid du Colombier error(Eperm);
743b7b24591SDavid du Colombier
7449a747e4fSDavid du Colombier /* validate kernel addresses */
7453e12c5d1SDavid du Colombier if(offset < (ulong)end) {
7463e12c5d1SDavid du Colombier if(offset+n > (ulong)end)
7473e12c5d1SDavid du Colombier n = (ulong)end - offset;
7483e12c5d1SDavid du Colombier memmove(a, (char*)offset, n);
7493e12c5d1SDavid du Colombier return n;
7503e12c5d1SDavid du Colombier }
7514de34a7eSDavid du Colombier for(i=0; i<nelem(conf.mem); i++){
7524de34a7eSDavid du Colombier cm = &conf.mem[i];
75326ad7229SDavid du Colombier /* klimit-1 because klimit might be zero! */
75426ad7229SDavid du Colombier if(cm->kbase <= offset && offset <= cm->klimit-1){
75526ad7229SDavid du Colombier if(offset+n >= cm->klimit-1)
7564de34a7eSDavid du Colombier n = cm->klimit - offset;
7573e12c5d1SDavid du Colombier memmove(a, (char*)offset, n);
7583e12c5d1SDavid du Colombier return n;
7593e12c5d1SDavid du Colombier }
7603e12c5d1SDavid du Colombier }
7617dd7cddfSDavid du Colombier error(Ebadarg);
7629a747e4fSDavid du Colombier
7637dd7cddfSDavid du Colombier case Qprofile:
7647dd7cddfSDavid du Colombier s = p->seg[TSEG];
7657dd7cddfSDavid du Colombier if(s == 0 || s->profile == 0)
7667dd7cddfSDavid du Colombier error("profile is off");
7677dd7cddfSDavid du Colombier i = (s->top-s->base)>>LRESPROF;
7687dd7cddfSDavid du Colombier i *= sizeof(*s->profile);
7697dd7cddfSDavid du Colombier if(offset >= i)
7707dd7cddfSDavid du Colombier return 0;
7717dd7cddfSDavid du Colombier if(offset+n > i)
7727dd7cddfSDavid du Colombier n = i - offset;
7737dd7cddfSDavid du Colombier memmove(a, ((char*)s->profile)+offset, n);
7747dd7cddfSDavid du Colombier return n;
7753e12c5d1SDavid du Colombier
7763e12c5d1SDavid du Colombier case Qnote:
7773e12c5d1SDavid du Colombier qlock(&p->debug);
7783e12c5d1SDavid du Colombier if(waserror()){
7793e12c5d1SDavid du Colombier qunlock(&p->debug);
7803e12c5d1SDavid du Colombier nexterror();
7813e12c5d1SDavid du Colombier }
7823e12c5d1SDavid du Colombier if(p->pid != PID(c->qid))
7833e12c5d1SDavid du Colombier error(Eprocdied);
7849a747e4fSDavid du Colombier if(n < 1) /* must accept at least the '\0' */
7853e12c5d1SDavid du Colombier error(Etoosmall);
7867dd7cddfSDavid du Colombier if(p->nnote == 0)
7873e12c5d1SDavid du Colombier n = 0;
7883e12c5d1SDavid du Colombier else {
7899a747e4fSDavid du Colombier m = strlen(p->note[0].msg) + 1;
7909a747e4fSDavid du Colombier if(m > n)
7919a747e4fSDavid du Colombier m = n;
7929a747e4fSDavid du Colombier memmove(va, p->note[0].msg, m);
7939a747e4fSDavid du Colombier ((char*)va)[m-1] = '\0';
7947dd7cddfSDavid du Colombier p->nnote--;
7957dd7cddfSDavid du Colombier memmove(p->note, p->note+1, p->nnote*sizeof(Note));
7969a747e4fSDavid du Colombier n = m;
7973e12c5d1SDavid du Colombier }
7987dd7cddfSDavid du Colombier if(p->nnote == 0)
7993e12c5d1SDavid du Colombier p->notepending = 0;
8003e12c5d1SDavid du Colombier poperror();
8013e12c5d1SDavid du Colombier qunlock(&p->debug);
8023e12c5d1SDavid du Colombier return n;
8033e12c5d1SDavid du Colombier
8043e12c5d1SDavid du Colombier case Qproc:
8053e12c5d1SDavid du Colombier if(offset >= sizeof(Proc))
8063e12c5d1SDavid du Colombier return 0;
8073e12c5d1SDavid du Colombier if(offset+n > sizeof(Proc))
8083e12c5d1SDavid du Colombier n = sizeof(Proc) - offset;
8093e12c5d1SDavid du Colombier memmove(a, ((char*)p)+offset, n);
8103e12c5d1SDavid du Colombier return n;
8113e12c5d1SDavid du Colombier
8127dd7cddfSDavid du Colombier case Qregs:
8137dd7cddfSDavid du Colombier rptr = (uchar*)p->dbgreg;
8147dd7cddfSDavid du Colombier rsize = sizeof(Ureg);
8157dd7cddfSDavid du Colombier goto regread;
8167dd7cddfSDavid du Colombier
8177dd7cddfSDavid du Colombier case Qkregs:
8187dd7cddfSDavid du Colombier memset(&kur, 0, sizeof(Ureg));
8197dd7cddfSDavid du Colombier setkernur(&kur, p);
8207dd7cddfSDavid du Colombier rptr = (uchar*)&kur;
8217dd7cddfSDavid du Colombier rsize = sizeof(Ureg);
8227dd7cddfSDavid du Colombier goto regread;
8237dd7cddfSDavid du Colombier
8247dd7cddfSDavid du Colombier case Qfpregs:
8257dd7cddfSDavid du Colombier rptr = (uchar*)&p->fpsave;
8267dd7cddfSDavid du Colombier rsize = sizeof(FPsave);
8277dd7cddfSDavid du Colombier regread:
8287dd7cddfSDavid du Colombier if(rptr == 0)
8297dd7cddfSDavid du Colombier error(Enoreg);
8307dd7cddfSDavid du Colombier if(offset >= rsize)
8317dd7cddfSDavid du Colombier return 0;
8327dd7cddfSDavid du Colombier if(offset+n > rsize)
8337dd7cddfSDavid du Colombier n = rsize - offset;
8347dd7cddfSDavid du Colombier memmove(a, rptr+offset, n);
8357dd7cddfSDavid du Colombier return n;
8367dd7cddfSDavid du Colombier
8373e12c5d1SDavid du Colombier case Qstatus:
8383e12c5d1SDavid du Colombier if(offset >= STATSIZE)
8393e12c5d1SDavid du Colombier return 0;
8403e12c5d1SDavid du Colombier if(offset+n > STATSIZE)
8413e12c5d1SDavid du Colombier n = STATSIZE - offset;
8423e12c5d1SDavid du Colombier
8433e12c5d1SDavid du Colombier sps = p->psstate;
8443e12c5d1SDavid du Colombier if(sps == 0)
8453e12c5d1SDavid du Colombier sps = statename[p->state];
846bd389b36SDavid du Colombier memset(statbuf, ' ', sizeof statbuf);
847a650be7dSDavid du Colombier readstr(0, statbuf+0*KNAMELEN, KNAMELEN-1, p->text);
848a650be7dSDavid du Colombier readstr(0, statbuf+1*KNAMELEN, KNAMELEN-1, p->user);
849a650be7dSDavid du Colombier readstr(0, statbuf+2*KNAMELEN, 11, sps);
8509a747e4fSDavid du Colombier j = 2*KNAMELEN + 12;
8513e12c5d1SDavid du Colombier
8523e12c5d1SDavid du Colombier for(i = 0; i < 6; i++) {
8533e12c5d1SDavid du Colombier l = p->time[i];
8543e12c5d1SDavid du Colombier if(i == TReal)
8553e12c5d1SDavid du Colombier l = MACHP(0)->ticks - l;
8563e12c5d1SDavid du Colombier l = TK2MS(l);
8573e12c5d1SDavid du Colombier readnum(0, statbuf+j+NUMSIZE*i, NUMSIZE, l, NUMSIZE);
8583e12c5d1SDavid du Colombier }
8593e12c5d1SDavid du Colombier /* ignore stack, which is mostly non-existent */
8603e12c5d1SDavid du Colombier l = 0;
8613e12c5d1SDavid du Colombier for(i=1; i<NSEG; i++){
8623e12c5d1SDavid du Colombier s = p->seg[i];
8633e12c5d1SDavid du Colombier if(s)
8643e12c5d1SDavid du Colombier l += s->top - s->base;
8653e12c5d1SDavid du Colombier }
8663e12c5d1SDavid du Colombier readnum(0, statbuf+j+NUMSIZE*6, NUMSIZE, l>>10, NUMSIZE);
8677dd7cddfSDavid du Colombier readnum(0, statbuf+j+NUMSIZE*7, NUMSIZE, p->basepri, NUMSIZE);
8687dd7cddfSDavid du Colombier readnum(0, statbuf+j+NUMSIZE*8, NUMSIZE, p->priority, NUMSIZE);
8693e12c5d1SDavid du Colombier memmove(a, statbuf+offset, n);
8703e12c5d1SDavid du Colombier return n;
8713e12c5d1SDavid du Colombier
8723e12c5d1SDavid du Colombier case Qsegment:
8733e12c5d1SDavid du Colombier j = 0;
8747dd7cddfSDavid du Colombier for(i = 0; i < NSEG; i++) {
8757dd7cddfSDavid du Colombier sg = p->seg[i];
8767dd7cddfSDavid du Colombier if(sg == 0)
8777dd7cddfSDavid du Colombier continue;
878*4e3613abSDavid du Colombier j += snprint(statbuf+j, sizeof statbuf - j,
879*4e3613abSDavid du Colombier "%-6s %c%c %.8lux %.8lux %4ld\n",
8807dd7cddfSDavid du Colombier sname[sg->type&SG_TYPE],
8817dd7cddfSDavid du Colombier sg->type&SG_RONLY ? 'R' : ' ',
8827dd7cddfSDavid du Colombier sg->profile ? 'P' : ' ',
8833e12c5d1SDavid du Colombier sg->base, sg->top, sg->ref);
8847dd7cddfSDavid du Colombier }
8853e12c5d1SDavid du Colombier if(offset >= j)
8863e12c5d1SDavid du Colombier return 0;
8873e12c5d1SDavid du Colombier if(offset+n > j)
8883e12c5d1SDavid du Colombier n = j-offset;
8893e12c5d1SDavid du Colombier if(n == 0 && offset == 0)
8903e12c5d1SDavid du Colombier exhausted("segments");
8913e12c5d1SDavid du Colombier memmove(a, &statbuf[offset], n);
8923e12c5d1SDavid du Colombier return n;
893219b2ee8SDavid du Colombier
894219b2ee8SDavid du Colombier case Qwait:
895219b2ee8SDavid du Colombier if(!canqlock(&p->qwaitr))
896219b2ee8SDavid du Colombier error(Einuse);
897219b2ee8SDavid du Colombier
898219b2ee8SDavid du Colombier if(waserror()) {
899219b2ee8SDavid du Colombier qunlock(&p->qwaitr);
900219b2ee8SDavid du Colombier nexterror();
901219b2ee8SDavid du Colombier }
902219b2ee8SDavid du Colombier
903219b2ee8SDavid du Colombier lock(&p->exl);
9047dd7cddfSDavid du Colombier if(up == p && p->nchild == 0 && p->waitq == 0) {
905219b2ee8SDavid du Colombier unlock(&p->exl);
906219b2ee8SDavid du Colombier error(Enochild);
907219b2ee8SDavid du Colombier }
9087dd7cddfSDavid du Colombier pid = p->pid;
909219b2ee8SDavid du Colombier while(p->waitq == 0) {
910219b2ee8SDavid du Colombier unlock(&p->exl);
911219b2ee8SDavid du Colombier sleep(&p->waitr, haswaitq, p);
9127dd7cddfSDavid du Colombier if(p->pid != pid)
9137dd7cddfSDavid du Colombier error(Eprocdied);
914219b2ee8SDavid du Colombier lock(&p->exl);
915219b2ee8SDavid du Colombier }
916219b2ee8SDavid du Colombier wq = p->waitq;
917219b2ee8SDavid du Colombier p->waitq = wq->next;
918219b2ee8SDavid du Colombier p->nwait--;
919219b2ee8SDavid du Colombier unlock(&p->exl);
920219b2ee8SDavid du Colombier
921219b2ee8SDavid du Colombier qunlock(&p->qwaitr);
922219b2ee8SDavid du Colombier poperror();
9239a747e4fSDavid du Colombier n = snprint(a, n, "%d %lud %lud %lud %q",
9249a747e4fSDavid du Colombier wq->w.pid,
9259a747e4fSDavid du Colombier wq->w.time[TUser], wq->w.time[TSys], wq->w.time[TReal],
9269a747e4fSDavid du Colombier wq->w.msg);
927219b2ee8SDavid du Colombier free(wq);
9289a747e4fSDavid du Colombier return n;
9297dd7cddfSDavid du Colombier
9307dd7cddfSDavid du Colombier case Qns:
9317dd7cddfSDavid du Colombier qlock(&p->debug);
9327dd7cddfSDavid du Colombier if(waserror()){
9337dd7cddfSDavid du Colombier qunlock(&p->debug);
9347dd7cddfSDavid du Colombier nexterror();
9357dd7cddfSDavid du Colombier }
9367dd7cddfSDavid du Colombier if(p->pgrp == nil || p->pid != PID(c->qid))
9377dd7cddfSDavid du Colombier error(Eprocdied);
9387dd7cddfSDavid du Colombier mw = c->aux;
939aa72973aSDavid du Colombier if(mw == nil)
940aa72973aSDavid du Colombier error(Enomem);
9417dd7cddfSDavid du Colombier if(mw->cddone){
9427dd7cddfSDavid du Colombier qunlock(&p->debug);
9437dd7cddfSDavid du Colombier poperror();
9447dd7cddfSDavid du Colombier return 0;
9457dd7cddfSDavid du Colombier }
9467dd7cddfSDavid du Colombier mntscan(mw, p);
9477dd7cddfSDavid du Colombier if(mw->mh == 0){
9487dd7cddfSDavid du Colombier mw->cddone = 1;
9494afe124fSDavid du Colombier i = snprint(a, n, "cd %s\n", p->dot->path->s);
9507dd7cddfSDavid du Colombier qunlock(&p->debug);
9517dd7cddfSDavid du Colombier poperror();
9527dd7cddfSDavid du Colombier return i;
9537dd7cddfSDavid du Colombier }
9549a747e4fSDavid du Colombier int2flag(mw->cm->mflag, flag);
9554afe124fSDavid du Colombier if(strcmp(mw->cm->to->path->s, "#M") == 0){
9567dd7cddfSDavid du Colombier srv = srvname(mw->cm->to->mchan);
9579a747e4fSDavid du Colombier i = snprint(a, n, "mount %s %s %s %s\n", flag,
9584afe124fSDavid du Colombier srv==nil? mw->cm->to->mchan->path->s : srv,
9594afe124fSDavid du Colombier mw->mh->from->path->s, mw->cm->spec? mw->cm->spec : "");
9607dd7cddfSDavid du Colombier free(srv);
9617dd7cddfSDavid du Colombier }else
9627dd7cddfSDavid du Colombier i = snprint(a, n, "bind %s %s %s\n", flag,
9634afe124fSDavid du Colombier mw->cm->to->path->s, mw->mh->from->path->s);
9647dd7cddfSDavid du Colombier qunlock(&p->debug);
9657dd7cddfSDavid du Colombier poperror();
9667dd7cddfSDavid du Colombier return i;
9677dd7cddfSDavid du Colombier
968219b2ee8SDavid du Colombier case Qnoteid:
969219b2ee8SDavid du Colombier return readnum(offset, va, n, p->noteid, NUMSIZE);
9707dd7cddfSDavid du Colombier case Qfd:
9717dd7cddfSDavid du Colombier return procfds(p, va, n, offset);
9723e12c5d1SDavid du Colombier }
9733e12c5d1SDavid du Colombier error(Egreg);
9743e12c5d1SDavid du Colombier return 0; /* not reached */
9753e12c5d1SDavid du Colombier }
9763e12c5d1SDavid du Colombier
9777dd7cddfSDavid du Colombier void
mntscan(Mntwalk * mw,Proc * p)9787dd7cddfSDavid du Colombier mntscan(Mntwalk *mw, Proc *p)
9797dd7cddfSDavid du Colombier {
9807dd7cddfSDavid du Colombier Pgrp *pg;
9817dd7cddfSDavid du Colombier Mount *t;
9827dd7cddfSDavid du Colombier Mhead *f;
9837dd7cddfSDavid du Colombier int nxt, i;
9847dd7cddfSDavid du Colombier ulong last, bestmid;
9853e12c5d1SDavid du Colombier
9867dd7cddfSDavid du Colombier pg = p->pgrp;
9877dd7cddfSDavid du Colombier rlock(&pg->ns);
9887dd7cddfSDavid du Colombier
9897dd7cddfSDavid du Colombier nxt = 0;
9907dd7cddfSDavid du Colombier bestmid = ~0;
9917dd7cddfSDavid du Colombier
9927dd7cddfSDavid du Colombier last = 0;
9937dd7cddfSDavid du Colombier if(mw->mh)
9947dd7cddfSDavid du Colombier last = mw->cm->mountid;
9957dd7cddfSDavid du Colombier
9967dd7cddfSDavid du Colombier for(i = 0; i < MNTHASH; i++) {
9977dd7cddfSDavid du Colombier for(f = pg->mnthash[i]; f; f = f->hash) {
9987dd7cddfSDavid du Colombier for(t = f->mount; t; t = t->next) {
9997dd7cddfSDavid du Colombier if(mw->mh == 0 ||
10007dd7cddfSDavid du Colombier (t->mountid > last && t->mountid < bestmid)) {
10017dd7cddfSDavid du Colombier mw->cm = t;
10027dd7cddfSDavid du Colombier mw->mh = f;
10037dd7cddfSDavid du Colombier bestmid = mw->cm->mountid;
10047dd7cddfSDavid du Colombier nxt = 1;
10057dd7cddfSDavid du Colombier }
10067dd7cddfSDavid du Colombier }
10077dd7cddfSDavid du Colombier }
10087dd7cddfSDavid du Colombier }
10097dd7cddfSDavid du Colombier if(nxt == 0)
10107dd7cddfSDavid du Colombier mw->mh = 0;
10117dd7cddfSDavid du Colombier
10127dd7cddfSDavid du Colombier runlock(&pg->ns);
10137dd7cddfSDavid du Colombier }
10147dd7cddfSDavid du Colombier
10157dd7cddfSDavid du Colombier static long
procwrite(Chan * c,void * va,long n,vlong off)10167dd7cddfSDavid du Colombier procwrite(Chan *c, void *va, long n, vlong off)
10173e12c5d1SDavid du Colombier {
1018d9306527SDavid du Colombier int id, m;
1019219b2ee8SDavid du Colombier Proc *p, *t, *et;
1020d9306527SDavid du Colombier char *a, *arg, buf[ERRMAX];
10217dd7cddfSDavid du Colombier ulong offset = off;
10223e12c5d1SDavid du Colombier
10237dd7cddfSDavid du Colombier a = va;
10249a747e4fSDavid du Colombier if(c->qid.type & QTDIR)
10253e12c5d1SDavid du Colombier error(Eisdir);
10263e12c5d1SDavid du Colombier
10273e12c5d1SDavid du Colombier p = proctab(SLOT(c->qid));
10283e12c5d1SDavid du Colombier
10297dd7cddfSDavid du Colombier /* Use the remembered noteid in the channel rather
10307dd7cddfSDavid du Colombier * than the process pgrpid
1031219b2ee8SDavid du Colombier */
10323e12c5d1SDavid du Colombier if(QID(c->qid) == Qnotepg) {
10333e12c5d1SDavid du Colombier pgrpnote(NOTEID(c->pgrpid), va, n, NUser);
10343e12c5d1SDavid du Colombier return n;
10353e12c5d1SDavid du Colombier }
10363e12c5d1SDavid du Colombier
10373e12c5d1SDavid du Colombier qlock(&p->debug);
10383e12c5d1SDavid du Colombier if(waserror()){
10393e12c5d1SDavid du Colombier qunlock(&p->debug);
10403e12c5d1SDavid du Colombier nexterror();
10413e12c5d1SDavid du Colombier }
10423e12c5d1SDavid du Colombier if(p->pid != PID(c->qid))
10433e12c5d1SDavid du Colombier error(Eprocdied);
10443e12c5d1SDavid du Colombier
10453e12c5d1SDavid du Colombier switch(QID(c->qid)){
1046d9306527SDavid du Colombier case Qargs:
1047d9306527SDavid du Colombier if(n == 0)
1048d9306527SDavid du Colombier error(Eshort);
1049d9306527SDavid du Colombier if(n >= ERRMAX)
1050d9306527SDavid du Colombier error(Etoobig);
1051d9306527SDavid du Colombier arg = malloc(n+1);
1052d9306527SDavid du Colombier if(arg == nil)
1053d9306527SDavid du Colombier error(Enomem);
1054d9306527SDavid du Colombier memmove(arg, va, n);
1055d9306527SDavid du Colombier m = n;
1056d9306527SDavid du Colombier if(arg[m-1] != 0)
1057d9306527SDavid du Colombier arg[m++] = 0;
1058d9306527SDavid du Colombier free(p->args);
1059d9306527SDavid du Colombier p->nargs = m;
1060d9306527SDavid du Colombier p->args = arg;
1061d9306527SDavid du Colombier p->setargs = 1;
1062d9306527SDavid du Colombier break;
1063d9306527SDavid du Colombier
10643e12c5d1SDavid du Colombier case Qmem:
10653e12c5d1SDavid du Colombier if(p->state != Stopped)
10663e12c5d1SDavid du Colombier error(Ebadctl);
10673e12c5d1SDavid du Colombier
10683e12c5d1SDavid du Colombier n = procctlmemio(p, offset, n, va, 0);
10693e12c5d1SDavid du Colombier break;
10703e12c5d1SDavid du Colombier
10717dd7cddfSDavid du Colombier case Qregs:
10727dd7cddfSDavid du Colombier if(offset >= sizeof(Ureg))
107309a9ed3fSDavid du Colombier n = 0;
107409a9ed3fSDavid du Colombier else if(offset+n > sizeof(Ureg))
10757dd7cddfSDavid du Colombier n = sizeof(Ureg) - offset;
10767dd7cddfSDavid du Colombier if(p->dbgreg == 0)
10777dd7cddfSDavid du Colombier error(Enoreg);
10787dd7cddfSDavid du Colombier setregisters(p->dbgreg, (char*)(p->dbgreg)+offset, va, n);
10797dd7cddfSDavid du Colombier break;
10807dd7cddfSDavid du Colombier
10817dd7cddfSDavid du Colombier case Qfpregs:
10827dd7cddfSDavid du Colombier if(offset >= sizeof(FPsave))
108309a9ed3fSDavid du Colombier n = 0;
108409a9ed3fSDavid du Colombier else if(offset+n > sizeof(FPsave))
10857dd7cddfSDavid du Colombier n = sizeof(FPsave) - offset;
10867dd7cddfSDavid du Colombier memmove((uchar*)&p->fpsave+offset, va, n);
10877dd7cddfSDavid du Colombier break;
10887dd7cddfSDavid du Colombier
10893e12c5d1SDavid du Colombier case Qctl:
10903e12c5d1SDavid du Colombier procctlreq(p, va, n);
10913e12c5d1SDavid du Colombier break;
10923e12c5d1SDavid du Colombier
10933e12c5d1SDavid du Colombier case Qnote:
10943e12c5d1SDavid du Colombier if(p->kp)
10953e12c5d1SDavid du Colombier error(Eperm);
10969a747e4fSDavid du Colombier if(n >= ERRMAX-1)
10973e12c5d1SDavid du Colombier error(Etoobig);
10983e12c5d1SDavid du Colombier memmove(buf, va, n);
10993e12c5d1SDavid du Colombier buf[n] = 0;
11003e12c5d1SDavid du Colombier if(!postnote(p, 0, buf, NUser))
11013e12c5d1SDavid du Colombier error("note not posted");
11023e12c5d1SDavid du Colombier break;
1103219b2ee8SDavid du Colombier case Qnoteid:
1104219b2ee8SDavid du Colombier id = atoi(a);
1105219b2ee8SDavid du Colombier if(id == p->pid) {
1106219b2ee8SDavid du Colombier p->noteid = id;
1107219b2ee8SDavid du Colombier break;
1108219b2ee8SDavid du Colombier }
1109219b2ee8SDavid du Colombier t = proctab(0);
1110219b2ee8SDavid du Colombier for(et = t+conf.nproc; t < et; t++) {
111111c9ee8bSDavid du Colombier if(t->state == Dead)
111211c9ee8bSDavid du Colombier continue;
1113219b2ee8SDavid du Colombier if(id == t->noteid) {
1114219b2ee8SDavid du Colombier if(strcmp(p->user, t->user) != 0)
1115219b2ee8SDavid du Colombier error(Eperm);
1116219b2ee8SDavid du Colombier p->noteid = id;
1117219b2ee8SDavid du Colombier break;
1118219b2ee8SDavid du Colombier }
1119219b2ee8SDavid du Colombier }
1120219b2ee8SDavid du Colombier if(p->noteid != id)
1121219b2ee8SDavid du Colombier error(Ebadarg);
1122219b2ee8SDavid du Colombier break;
11233e12c5d1SDavid du Colombier default:
11243e12c5d1SDavid du Colombier pprint("unknown qid in procwrite\n");
11253e12c5d1SDavid du Colombier error(Egreg);
11263e12c5d1SDavid du Colombier }
11273e12c5d1SDavid du Colombier poperror();
11283e12c5d1SDavid du Colombier qunlock(&p->debug);
11293e12c5d1SDavid du Colombier return n;
11303e12c5d1SDavid du Colombier }
11313e12c5d1SDavid du Colombier
11327dd7cddfSDavid du Colombier Dev procdevtab = {
11337dd7cddfSDavid du Colombier 'p',
11347dd7cddfSDavid du Colombier "proc",
11357dd7cddfSDavid du Colombier
11367dd7cddfSDavid du Colombier devreset,
11377dd7cddfSDavid du Colombier procinit,
11389a747e4fSDavid du Colombier devshutdown,
11397dd7cddfSDavid du Colombier procattach,
11407dd7cddfSDavid du Colombier procwalk,
11417dd7cddfSDavid du Colombier procstat,
11427dd7cddfSDavid du Colombier procopen,
11437dd7cddfSDavid du Colombier devcreate,
11447dd7cddfSDavid du Colombier procclose,
11457dd7cddfSDavid du Colombier procread,
11467dd7cddfSDavid du Colombier devbread,
11477dd7cddfSDavid du Colombier procwrite,
11487dd7cddfSDavid du Colombier devbwrite,
11497dd7cddfSDavid du Colombier devremove,
11507dd7cddfSDavid du Colombier procwstat,
11517dd7cddfSDavid du Colombier };
11527dd7cddfSDavid du Colombier
11533e12c5d1SDavid du Colombier Chan*
proctext(Chan * c,Proc * p)11543e12c5d1SDavid du Colombier proctext(Chan *c, Proc *p)
11553e12c5d1SDavid du Colombier {
11563e12c5d1SDavid du Colombier Chan *tc;
11573e12c5d1SDavid du Colombier Image *i;
11583e12c5d1SDavid du Colombier Segment *s;
11593e12c5d1SDavid du Colombier
11603e12c5d1SDavid du Colombier s = p->seg[TSEG];
11613e12c5d1SDavid du Colombier if(s == 0)
11623e12c5d1SDavid du Colombier error(Enonexist);
11633e12c5d1SDavid du Colombier if(p->state==Dead)
11643e12c5d1SDavid du Colombier error(Eprocdied);
11653e12c5d1SDavid du Colombier
11663e12c5d1SDavid du Colombier lock(s);
11673e12c5d1SDavid du Colombier i = s->image;
11683e12c5d1SDavid du Colombier if(i == 0) {
11693e12c5d1SDavid du Colombier unlock(s);
11703e12c5d1SDavid du Colombier error(Eprocdied);
11713e12c5d1SDavid du Colombier }
11723e12c5d1SDavid du Colombier unlock(s);
11733e12c5d1SDavid du Colombier
11743e12c5d1SDavid du Colombier lock(i);
11753e12c5d1SDavid du Colombier if(waserror()) {
11763e12c5d1SDavid du Colombier unlock(i);
11773e12c5d1SDavid du Colombier nexterror();
11783e12c5d1SDavid du Colombier }
11793e12c5d1SDavid du Colombier
11803e12c5d1SDavid du Colombier tc = i->c;
11813e12c5d1SDavid du Colombier if(tc == 0)
11823e12c5d1SDavid du Colombier error(Eprocdied);
11833e12c5d1SDavid du Colombier
11843e12c5d1SDavid du Colombier if(incref(tc) == 1 || (tc->flag&COPEN) == 0 || tc->mode!=OREAD) {
11857dd7cddfSDavid du Colombier cclose(tc);
11863e12c5d1SDavid du Colombier error(Eprocdied);
11873e12c5d1SDavid du Colombier }
11883e12c5d1SDavid du Colombier
118909474398SDavid du Colombier if(p->pid != PID(c->qid)){
119009474398SDavid du Colombier cclose(tc);
11913e12c5d1SDavid du Colombier error(Eprocdied);
119209474398SDavid du Colombier }
11933e12c5d1SDavid du Colombier
11943e12c5d1SDavid du Colombier unlock(i);
11953e12c5d1SDavid du Colombier poperror();
11963e12c5d1SDavid du Colombier
11973e12c5d1SDavid du Colombier return tc;
11983e12c5d1SDavid du Colombier }
11993e12c5d1SDavid du Colombier
12003e12c5d1SDavid du Colombier void
procstopwait(Proc * p,int ctl)12013e12c5d1SDavid du Colombier procstopwait(Proc *p, int ctl)
12023e12c5d1SDavid du Colombier {
12033e12c5d1SDavid du Colombier int pid;
12043e12c5d1SDavid du Colombier
12053e12c5d1SDavid du Colombier if(p->pdbg)
12063e12c5d1SDavid du Colombier error(Einuse);
12079a747e4fSDavid du Colombier if(procstopped(p) || p->state == Broken)
12083e12c5d1SDavid du Colombier return;
12093e12c5d1SDavid du Colombier
12103e12c5d1SDavid du Colombier if(ctl != 0)
12113e12c5d1SDavid du Colombier p->procctl = ctl;
12127dd7cddfSDavid du Colombier p->pdbg = up;
12133e12c5d1SDavid du Colombier pid = p->pid;
12143e12c5d1SDavid du Colombier qunlock(&p->debug);
12157dd7cddfSDavid du Colombier up->psstate = "Stopwait";
12163e12c5d1SDavid du Colombier if(waserror()) {
12173e12c5d1SDavid du Colombier p->pdbg = 0;
12183e12c5d1SDavid du Colombier qlock(&p->debug);
12193e12c5d1SDavid du Colombier nexterror();
12203e12c5d1SDavid du Colombier }
12217dd7cddfSDavid du Colombier sleep(&up->sleep, procstopped, p);
12223e12c5d1SDavid du Colombier poperror();
12233e12c5d1SDavid du Colombier qlock(&p->debug);
12243e12c5d1SDavid du Colombier if(p->pid != pid)
12253e12c5d1SDavid du Colombier error(Eprocdied);
12263e12c5d1SDavid du Colombier }
12273e12c5d1SDavid du Colombier
12289a747e4fSDavid du Colombier static void
procctlcloseone(Proc * p,Fgrp * f,int fd)12299a747e4fSDavid du Colombier procctlcloseone(Proc *p, Fgrp *f, int fd)
12309a747e4fSDavid du Colombier {
12319a747e4fSDavid du Colombier Chan *c;
12329a747e4fSDavid du Colombier
12339a747e4fSDavid du Colombier c = f->fd[fd];
12349a747e4fSDavid du Colombier if(c == nil)
12359a747e4fSDavid du Colombier return;
12369a747e4fSDavid du Colombier f->fd[fd] = nil;
12379a747e4fSDavid du Colombier unlock(f);
12389a747e4fSDavid du Colombier qunlock(&p->debug);
12399a747e4fSDavid du Colombier cclose(c);
12409a747e4fSDavid du Colombier qlock(&p->debug);
12419a747e4fSDavid du Colombier lock(f);
12429a747e4fSDavid du Colombier }
12439a747e4fSDavid du Colombier
12443e12c5d1SDavid du Colombier void
procctlclosefiles(Proc * p,int all,int fd)12459a747e4fSDavid du Colombier procctlclosefiles(Proc *p, int all, int fd)
12463e12c5d1SDavid du Colombier {
1247219b2ee8SDavid du Colombier int i;
124880ee5cbfSDavid du Colombier Fgrp *f;
124980ee5cbfSDavid du Colombier
125080ee5cbfSDavid du Colombier f = p->fgrp;
125180ee5cbfSDavid du Colombier if(f == nil)
125280ee5cbfSDavid du Colombier error(Eprocdied);
12537dd7cddfSDavid du Colombier
12547dd7cddfSDavid du Colombier lock(f);
12557dd7cddfSDavid du Colombier f->ref++;
12569a747e4fSDavid du Colombier if(all)
12579a747e4fSDavid du Colombier for(i = 0; i < f->maxfd; i++)
12589a747e4fSDavid du Colombier procctlcloseone(p, f, i);
12599a747e4fSDavid du Colombier else
12609a747e4fSDavid du Colombier procctlcloseone(p, f, fd);
12617dd7cddfSDavid du Colombier unlock(f);
12627dd7cddfSDavid du Colombier closefgrp(f);
12637dd7cddfSDavid du Colombier }
12647dd7cddfSDavid du Colombier
1265e288d156SDavid du Colombier static char *
parsetime(vlong * rt,char * s)1266e288d156SDavid du Colombier parsetime(vlong *rt, char *s)
1267e288d156SDavid du Colombier {
1268e288d156SDavid du Colombier uvlong ticks;
1269e288d156SDavid du Colombier ulong l;
1270e288d156SDavid du Colombier char *e, *p;
1271e288d156SDavid du Colombier static int p10[] = {100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10, 1};
1272e288d156SDavid du Colombier
1273e288d156SDavid du Colombier if (s == nil)
1274e288d156SDavid du Colombier return("missing value");
1275e288d156SDavid du Colombier ticks=strtoul(s, &e, 10);
1276e288d156SDavid du Colombier if (*e == '.'){
1277e288d156SDavid du Colombier p = e+1;
1278e288d156SDavid du Colombier l = strtoul(p, &e, 10);
1279e288d156SDavid du Colombier if(e-p > nelem(p10))
1280e288d156SDavid du Colombier return "too many digits after decimal point";
1281e288d156SDavid du Colombier if(e-p == 0)
1282e288d156SDavid du Colombier return "ill-formed number";
1283e288d156SDavid du Colombier l *= p10[e-p-1];
1284e288d156SDavid du Colombier }else
1285e288d156SDavid du Colombier l = 0;
1286e288d156SDavid du Colombier if (*e == '\0' || strcmp(e, "s") == 0){
1287e288d156SDavid du Colombier ticks = 1000000000 * ticks + l;
1288e288d156SDavid du Colombier }else if (strcmp(e, "ms") == 0){
1289e288d156SDavid du Colombier ticks = 1000000 * ticks + l/1000;
1290e288d156SDavid du Colombier }else if (strcmp(e, "µs") == 0 || strcmp(e, "us") == 0){
1291e288d156SDavid du Colombier ticks = 1000 * ticks + l/1000000;
1292e288d156SDavid du Colombier }else if (strcmp(e, "ns") != 0)
1293e288d156SDavid du Colombier return "unrecognized unit";
1294e288d156SDavid du Colombier *rt = ticks;
1295e288d156SDavid du Colombier return nil;
1296e288d156SDavid du Colombier }
1297e288d156SDavid du Colombier
12987dd7cddfSDavid du Colombier void
procctlreq(Proc * p,char * va,int n)12997dd7cddfSDavid du Colombier procctlreq(Proc *p, char *va, int n)
13007dd7cddfSDavid du Colombier {
13017dd7cddfSDavid du Colombier Segment *s;
1302a6a9e072SDavid du Colombier int npc, pri;
13039a747e4fSDavid du Colombier Cmdbuf *cb;
13049a747e4fSDavid du Colombier Cmdtab *ct;
1305e288d156SDavid du Colombier vlong time;
1306e288d156SDavid du Colombier char *e;
13072cca75a1SDavid du Colombier void (*pt)(Proc*, int, vlong);
13083e12c5d1SDavid du Colombier
13099a747e4fSDavid du Colombier if(p->kp) /* no ctl requests to kprocs */
13109a747e4fSDavid du Colombier error(Eperm);
13113e12c5d1SDavid du Colombier
13129a747e4fSDavid du Colombier cb = parsecmd(va, n);
13139a747e4fSDavid du Colombier if(waserror()){
13149a747e4fSDavid du Colombier free(cb);
13159a747e4fSDavid du Colombier nexterror();
13169a747e4fSDavid du Colombier }
13179a747e4fSDavid du Colombier
13189a747e4fSDavid du Colombier ct = lookupcmd(cb, proccmd, nelem(proccmd));
13199a747e4fSDavid du Colombier
13209a747e4fSDavid du Colombier switch(ct->index){
13219a747e4fSDavid du Colombier case CMclose:
13229a747e4fSDavid du Colombier procctlclosefiles(p, 0, atoi(cb->f[1]));
13239a747e4fSDavid du Colombier break;
13249a747e4fSDavid du Colombier case CMclosefiles:
13259a747e4fSDavid du Colombier procctlclosefiles(p, 1, 0);
13269a747e4fSDavid du Colombier break;
13279a747e4fSDavid du Colombier case CMhang:
13289a747e4fSDavid du Colombier p->hang = 1;
13299a747e4fSDavid du Colombier break;
13309a747e4fSDavid du Colombier case CMkill:
1331bd389b36SDavid du Colombier switch(p->state) {
1332bd389b36SDavid du Colombier case Broken:
1333bd389b36SDavid du Colombier unbreak(p);
1334bd389b36SDavid du Colombier break;
1335bd389b36SDavid du Colombier case Stopped:
1336bd389b36SDavid du Colombier p->procctl = Proc_exitme;
13372cca75a1SDavid du Colombier postnote(p, 0, "sys: killed", NExit);
13383e12c5d1SDavid du Colombier ready(p);
1339bd389b36SDavid du Colombier break;
1340bd389b36SDavid du Colombier default:
13413e12c5d1SDavid du Colombier p->procctl = Proc_exitme;
13422cca75a1SDavid du Colombier postnote(p, 0, "sys: killed", NExit);
13433e12c5d1SDavid du Colombier }
13449a747e4fSDavid du Colombier break;
13459a747e4fSDavid du Colombier case CMnohang:
1346219b2ee8SDavid du Colombier p->hang = 0;
13479a747e4fSDavid du Colombier break;
1348b7b24591SDavid du Colombier case CMnoswap:
1349b7b24591SDavid du Colombier p->noswap = 1;
1350b7b24591SDavid du Colombier break;
13519a747e4fSDavid du Colombier case CMpri:
1352a6a9e072SDavid du Colombier pri = atoi(cb->f[1]);
1353a6a9e072SDavid du Colombier if(pri > PriNormal && !iseve())
1354219b2ee8SDavid du Colombier error(Eperm);
1355a6a9e072SDavid du Colombier procpriority(p, pri, 0);
1356a6a9e072SDavid du Colombier break;
1357a6a9e072SDavid du Colombier case CMfixedpri:
135804b73bddSDavid du Colombier pri = atoi(cb->f[1]);
135904b73bddSDavid du Colombier if(pri > PriNormal && !iseve())
1360a6a9e072SDavid du Colombier error(Eperm);
136104b73bddSDavid du Colombier procpriority(p, pri, 1);
13629a747e4fSDavid du Colombier break;
13639a747e4fSDavid du Colombier case CMprivate:
13649a747e4fSDavid du Colombier p->privatemem = 1;
13659a747e4fSDavid du Colombier break;
13669a747e4fSDavid du Colombier case CMprofile:
13677dd7cddfSDavid du Colombier s = p->seg[TSEG];
13687dd7cddfSDavid du Colombier if(s == 0 || (s->type&SG_TYPE) != SG_TEXT)
13697dd7cddfSDavid du Colombier error(Ebadctl);
13707dd7cddfSDavid du Colombier if(s->profile != 0)
13717dd7cddfSDavid du Colombier free(s->profile);
13727dd7cddfSDavid du Colombier npc = (s->top-s->base)>>LRESPROF;
13737dd7cddfSDavid du Colombier s->profile = malloc(npc*sizeof(*s->profile));
13747dd7cddfSDavid du Colombier if(s->profile == 0)
13757dd7cddfSDavid du Colombier error(Enomem);
13769a747e4fSDavid du Colombier break;
13779a747e4fSDavid du Colombier case CMstart:
13789a747e4fSDavid du Colombier if(p->state != Stopped)
13793e12c5d1SDavid du Colombier error(Ebadctl);
13809a747e4fSDavid du Colombier ready(p);
13819a747e4fSDavid du Colombier break;
13829a747e4fSDavid du Colombier case CMstartstop:
13839a747e4fSDavid du Colombier if(p->state != Stopped)
13849a747e4fSDavid du Colombier error(Ebadctl);
13859a747e4fSDavid du Colombier p->procctl = Proc_traceme;
13869a747e4fSDavid du Colombier ready(p);
13879a747e4fSDavid du Colombier procstopwait(p, Proc_traceme);
13889a747e4fSDavid du Colombier break;
1389e288d156SDavid du Colombier case CMstartsyscall:
1390e288d156SDavid du Colombier if(p->state != Stopped)
1391e288d156SDavid du Colombier error(Ebadctl);
1392e288d156SDavid du Colombier p->procctl = Proc_tracesyscall;
1393e288d156SDavid du Colombier ready(p);
1394e288d156SDavid du Colombier procstopwait(p, Proc_tracesyscall);
1395e288d156SDavid du Colombier break;
13969a747e4fSDavid du Colombier case CMstop:
13979a747e4fSDavid du Colombier procstopwait(p, Proc_stopme);
13989a747e4fSDavid du Colombier break;
13999a747e4fSDavid du Colombier case CMwaitstop:
14009a747e4fSDavid du Colombier procstopwait(p, 0);
14019a747e4fSDavid du Colombier break;
14029a747e4fSDavid du Colombier case CMwired:
14039a747e4fSDavid du Colombier procwired(p, atoi(cb->f[1]));
14049a747e4fSDavid du Colombier break;
1405e288d156SDavid du Colombier case CMtrace:
1406179dd269SDavid du Colombier switch(cb->nf){
1407179dd269SDavid du Colombier case 1:
1408220e960cSDavid du Colombier p->trace ^= 1;
1409e288d156SDavid du Colombier break;
1410179dd269SDavid du Colombier case 2:
141125910e17SDavid du Colombier p->trace = (atoi(cb->f[1]) != 0);
1412179dd269SDavid du Colombier break;
1413179dd269SDavid du Colombier default:
1414179dd269SDavid du Colombier error("args");
1415179dd269SDavid du Colombier }
1416179dd269SDavid du Colombier break;
1417e288d156SDavid du Colombier /* real time */
1418e288d156SDavid du Colombier case CMperiod:
1419e288d156SDavid du Colombier if(p->edf == nil)
1420e288d156SDavid du Colombier edfinit(p);
14212cca75a1SDavid du Colombier if(e=parsetime(&time, cb->f[1])) /* time in ns */
1422e288d156SDavid du Colombier error(e);
1423e288d156SDavid du Colombier edfstop(p);
14242cca75a1SDavid du Colombier p->edf->T = time/1000; /* Edf times are in µs */
1425e288d156SDavid du Colombier break;
1426e288d156SDavid du Colombier case CMdeadline:
1427e288d156SDavid du Colombier if(p->edf == nil)
1428e288d156SDavid du Colombier edfinit(p);
1429e288d156SDavid du Colombier if(e=parsetime(&time, cb->f[1]))
1430e288d156SDavid du Colombier error(e);
1431e288d156SDavid du Colombier edfstop(p);
14322cca75a1SDavid du Colombier p->edf->D = time/1000;
1433e288d156SDavid du Colombier break;
1434e288d156SDavid du Colombier case CMcost:
1435e288d156SDavid du Colombier if(p->edf == nil)
1436e288d156SDavid du Colombier edfinit(p);
1437e288d156SDavid du Colombier if(e=parsetime(&time, cb->f[1]))
1438e288d156SDavid du Colombier error(e);
1439e288d156SDavid du Colombier edfstop(p);
14402cca75a1SDavid du Colombier p->edf->C = time/1000;
1441e288d156SDavid du Colombier break;
1442e288d156SDavid du Colombier case CMsporadic:
1443e288d156SDavid du Colombier if(p->edf == nil)
1444e288d156SDavid du Colombier edfinit(p);
1445e288d156SDavid du Colombier p->edf->flags |= Sporadic;
1446e288d156SDavid du Colombier break;
1447e288d156SDavid du Colombier case CMdeadlinenotes:
1448e288d156SDavid du Colombier if(p->edf == nil)
1449e288d156SDavid du Colombier edfinit(p);
1450e288d156SDavid du Colombier p->edf->flags |= Sendnotes;
1451e288d156SDavid du Colombier break;
1452e288d156SDavid du Colombier case CMadmit:
1453e288d156SDavid du Colombier if(p->edf == 0)
1454e288d156SDavid du Colombier error("edf params");
1455e288d156SDavid du Colombier if(e = edfadmit(p))
1456e288d156SDavid du Colombier error(e);
1457e288d156SDavid du Colombier break;
1458179dd269SDavid du Colombier case CMextra:
1459179dd269SDavid du Colombier if(p->edf == nil)
1460179dd269SDavid du Colombier edfinit(p);
1461179dd269SDavid du Colombier p->edf->flags |= Extratime;
1462179dd269SDavid du Colombier break;
1463e288d156SDavid du Colombier case CMexpel:
1464e288d156SDavid du Colombier if(p->edf)
1465e288d156SDavid du Colombier edfstop(p);
1466e288d156SDavid du Colombier break;
14672cca75a1SDavid du Colombier case CMevent:
14682cca75a1SDavid du Colombier pt = proctrace;
14692cca75a1SDavid du Colombier if(up->trace && pt)
14702cca75a1SDavid du Colombier pt(up, SUser, 0);
14712cca75a1SDavid du Colombier break;
14729a747e4fSDavid du Colombier }
14739a747e4fSDavid du Colombier
14749a747e4fSDavid du Colombier poperror();
14759a747e4fSDavid du Colombier free(cb);
14763e12c5d1SDavid du Colombier }
14773e12c5d1SDavid du Colombier
14783e12c5d1SDavid du Colombier int
procstopped(void * a)14793e12c5d1SDavid du Colombier procstopped(void *a)
14803e12c5d1SDavid du Colombier {
14813e12c5d1SDavid du Colombier Proc *p = a;
14823e12c5d1SDavid du Colombier return p->state == Stopped;
14833e12c5d1SDavid du Colombier }
14843e12c5d1SDavid du Colombier
14853e12c5d1SDavid du Colombier int
procctlmemio(Proc * p,ulong offset,int n,void * va,int read)14863e12c5d1SDavid du Colombier procctlmemio(Proc *p, ulong offset, int n, void *va, int read)
14873e12c5d1SDavid du Colombier {
14883e12c5d1SDavid du Colombier KMap *k;
14893e12c5d1SDavid du Colombier Pte *pte;
14903e12c5d1SDavid du Colombier Page *pg;
14913e12c5d1SDavid du Colombier Segment *s;
14923e12c5d1SDavid du Colombier ulong soff, l;
14933e12c5d1SDavid du Colombier char *a = va, *b;
14943e12c5d1SDavid du Colombier
14953e12c5d1SDavid du Colombier for(;;) {
14963e12c5d1SDavid du Colombier s = seg(p, offset, 1);
14973e12c5d1SDavid du Colombier if(s == 0)
14983e12c5d1SDavid du Colombier error(Ebadarg);
14993e12c5d1SDavid du Colombier
15003e12c5d1SDavid du Colombier if(offset+n >= s->top)
15013e12c5d1SDavid du Colombier n = s->top-offset;
15023e12c5d1SDavid du Colombier
15037dd7cddfSDavid du Colombier if(!read && (s->type&SG_TYPE) == SG_TEXT)
15043e12c5d1SDavid du Colombier s = txt2data(p, s);
15053e12c5d1SDavid du Colombier
15063e12c5d1SDavid du Colombier s->steal++;
15073e12c5d1SDavid du Colombier soff = offset-s->base;
15083e12c5d1SDavid du Colombier if(waserror()) {
15093e12c5d1SDavid du Colombier s->steal--;
15103e12c5d1SDavid du Colombier nexterror();
15113e12c5d1SDavid du Colombier }
15123e12c5d1SDavid du Colombier if(fixfault(s, offset, read, 0) == 0)
15133e12c5d1SDavid du Colombier break;
15143e12c5d1SDavid du Colombier poperror();
15153e12c5d1SDavid du Colombier s->steal--;
15163e12c5d1SDavid du Colombier }
15173e12c5d1SDavid du Colombier poperror();
15183e12c5d1SDavid du Colombier pte = s->map[soff/PTEMAPMEM];
15193e12c5d1SDavid du Colombier if(pte == 0)
15203e12c5d1SDavid du Colombier panic("procctlmemio");
15213e12c5d1SDavid du Colombier pg = pte->pages[(soff&(PTEMAPMEM-1))/BY2PG];
15223e12c5d1SDavid du Colombier if(pagedout(pg))
15233e12c5d1SDavid du Colombier panic("procctlmemio1");
15243e12c5d1SDavid du Colombier
15253e12c5d1SDavid du Colombier l = BY2PG - (offset&(BY2PG-1));
15263e12c5d1SDavid du Colombier if(n > l)
15273e12c5d1SDavid du Colombier n = l;
15283e12c5d1SDavid du Colombier
15293e12c5d1SDavid du Colombier k = kmap(pg);
15307dd7cddfSDavid du Colombier if(waserror()) {
15317dd7cddfSDavid du Colombier s->steal--;
15323e12c5d1SDavid du Colombier kunmap(k);
15337dd7cddfSDavid du Colombier nexterror();
15347dd7cddfSDavid du Colombier }
15357dd7cddfSDavid du Colombier b = (char*)VA(k);
15367dd7cddfSDavid du Colombier b += offset&(BY2PG-1);
15377dd7cddfSDavid du Colombier if(read == 1)
15387dd7cddfSDavid du Colombier memmove(a, b, n); /* This can fault */
15397dd7cddfSDavid du Colombier else
15407dd7cddfSDavid du Colombier memmove(b, a, n);
15417dd7cddfSDavid du Colombier kunmap(k);
15427dd7cddfSDavid du Colombier poperror();
15437dd7cddfSDavid du Colombier
15447dd7cddfSDavid du Colombier /* Ensure the process sees text page changes */
15457dd7cddfSDavid du Colombier if(s->flushme)
15467dd7cddfSDavid du Colombier memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
15473e12c5d1SDavid du Colombier
15483e12c5d1SDavid du Colombier s->steal--;
15493e12c5d1SDavid du Colombier
15503e12c5d1SDavid du Colombier if(read == 0)
15513e12c5d1SDavid du Colombier p->newtlb = 1;
15523e12c5d1SDavid du Colombier
15533e12c5d1SDavid du Colombier return n;
15543e12c5d1SDavid du Colombier }
15553e12c5d1SDavid du Colombier
15563e12c5d1SDavid du Colombier Segment*
txt2data(Proc * p,Segment * s)15573e12c5d1SDavid du Colombier txt2data(Proc *p, Segment *s)
15583e12c5d1SDavid du Colombier {
15593e12c5d1SDavid du Colombier int i;
15603e12c5d1SDavid du Colombier Segment *ps;
15613e12c5d1SDavid du Colombier
15623e12c5d1SDavid du Colombier ps = newseg(SG_DATA, s->base, s->size);
15633e12c5d1SDavid du Colombier ps->image = s->image;
15643e12c5d1SDavid du Colombier incref(ps->image);
15653e12c5d1SDavid du Colombier ps->fstart = s->fstart;
15663e12c5d1SDavid du Colombier ps->flen = s->flen;
15673e12c5d1SDavid du Colombier ps->flushme = 1;
15683e12c5d1SDavid du Colombier
15697dd7cddfSDavid du Colombier qlock(&p->seglock);
15703e12c5d1SDavid du Colombier for(i = 0; i < NSEG; i++)
15713e12c5d1SDavid du Colombier if(p->seg[i] == s)
15723e12c5d1SDavid du Colombier break;
15737dbf685cSDavid du Colombier if(i == NSEG)
15743e12c5d1SDavid du Colombier panic("segment gone");
15753e12c5d1SDavid du Colombier
15763e12c5d1SDavid du Colombier qunlock(&s->lk);
15773e12c5d1SDavid du Colombier putseg(s);
15783e12c5d1SDavid du Colombier qlock(&ps->lk);
15793e12c5d1SDavid du Colombier p->seg[i] = ps;
15807dd7cddfSDavid du Colombier qunlock(&p->seglock);
15813e12c5d1SDavid du Colombier
15823e12c5d1SDavid du Colombier return ps;
15833e12c5d1SDavid du Colombier }
1584bd389b36SDavid du Colombier
1585bd389b36SDavid du Colombier Segment*
data2txt(Segment * s)1586bd389b36SDavid du Colombier data2txt(Segment *s)
1587bd389b36SDavid du Colombier {
1588bd389b36SDavid du Colombier Segment *ps;
1589bd389b36SDavid du Colombier
1590bd389b36SDavid du Colombier ps = newseg(SG_TEXT, s->base, s->size);
1591bd389b36SDavid du Colombier ps->image = s->image;
1592bd389b36SDavid du Colombier incref(ps->image);
1593bd389b36SDavid du Colombier ps->fstart = s->fstart;
1594bd389b36SDavid du Colombier ps->flen = s->flen;
1595bd389b36SDavid du Colombier ps->flushme = 1;
1596bd389b36SDavid du Colombier
1597bd389b36SDavid du Colombier return ps;
1598bd389b36SDavid du Colombier }
1599