#include "ureg.h"
#include "edf.h"
+#include <pool.h>
+
enum
{
Qdir,
Qnoteid,
Qnotepg,
Qns,
+ Qppid,
Qproc,
Qregs,
Qsegment,
CMwaitstop,
CMwired,
CMtrace,
+ CMinterrupt,
+ CMnointerrupt,
/* real time */
CMperiod,
CMdeadline,
"noteid", {Qnoteid}, 0, 0664,
"notepg", {Qnotepg}, 0, 0000,
"ns", {Qns}, 0, 0444,
+ "ppid", {Qppid}, 0, 0444,
"proc", {Qproc}, 0, 0400,
"regs", {Qregs}, sizeof(Ureg), 0000,
"segment", {Qsegment}, 0, 0444,
CMwaitstop, "waitstop", 1,
CMwired, "wired", 2,
CMtrace, "trace", 0,
+ CMinterrupt, "interrupt", 1,
+ CMnointerrupt, "nointerrupt", 1,
CMperiod, "period", 2,
CMdeadline, "deadline", 2,
CMcost, "cost", 2,
};
/* Segment type from portdat.h */
-static char *sname[]={ "Text", "Data", "Bss", "Stack", "Shared", "Phys", };
+static char *sname[]={ "Text", "Data", "Bss", "Stack", "Shared", "Phys", "Fixed", };
/*
* Qids are, in path:
#define NOTEID(q) ((q).vers)
void procctlreq(Proc*, char*, int);
-int procctlmemio(Proc*, ulong, int, void*, int);
+long procctlmemio(Chan*, Proc*, uintptr, void*, long, int);
Chan* proctext(Chan*, Proc*);
-Segment* txt2data(Proc*, Segment*);
int procstopped(void*);
-void mntscan(Mntwalk*, Proc*);
+ulong procpagecount(Proc *);
static Traceevent *tevents;
static Lock tlock;
static int tproduced, tconsumed;
void (*proctrace)(Proc*, int, vlong);
-extern int unfair;
-
static void
profclock(Ureg *ur, Timer *)
{
Tos *tos;
- if(up == 0 || up->state != Running)
+ if(up == nil || up->state != Running)
return;
/* user profiling clock */
break;
case Qprofile:
q = p->seg[TSEG];
- if(q && q->profile) {
+ if(q != nil && q->profile != nil) {
len = (q->top-q->base)>>LRESPROF;
len *= sizeof(*q->profile);
}
error(Eperm);
lock(&tlock);
if (waserror()){
+ topens--;
unlock(&tlock);
nexterror();
}
- if (topens > 0)
+ if (topens++ > 0)
error("already open");
- topens++;
if (tevents == nil){
tevents = (Traceevent*)malloc(sizeof(Traceevent) * Nevents);
if(tevents == nil)
}
p = proctab(SLOT(c->qid));
- qlock(&p->debug);
+ eqlock(&p->debug);
if(waserror()){
qunlock(&p->debug);
nexterror();
tc->offset = 0;
qunlock(&p->debug);
poperror();
+ cclose(c);
return tc;
case Qproc:
case Qkregs:
case Qsegment:
case Qprofile:
+ case Qns:
case Qfd:
if(omode != OREAD)
error(Eperm);
case Qregs:
case Qfpregs:
case Qsyscall:
+ case Qppid:
nonone(p);
break;
- case Qns:
- if(omode != OREAD)
- error(Eperm);
- c->aux = malloc(sizeof(Mntwalk));
- break;
-
case Qnotepg:
nonone(p);
pg = p->pgrp;
if(pg == nil)
error(Eprocdied);
- if(omode!=OWRITE || pg->pgrpid == 1)
+ if(omode!=OWRITE)
error(Eperm);
c->pgrpid.path = pg->pgrpid+1;
c->pgrpid.vers = p->noteid;
break;
default:
- pprint("procopen %#lux\n", QID(c->qid));
+ print("procopen %#lux\n", QID(c->qid));
error(Egreg);
}
p = proctab(SLOT(c->qid));
nonone(p);
d = nil;
+
+ eqlock(&p->debug);
if(waserror()){
- free(d);
qunlock(&p->debug);
+ free(d);
nexterror();
}
- qlock(&p->debug);
if(p->pid != PID(c->qid))
error(Eprocdied);
- if(strcmp(up->user, p->user) != 0 && strcmp(up->user, eve) != 0)
+ if(strcmp(up->user, p->user) != 0 && !iseve())
error(Eperm);
d = smalloc(sizeof(Dir)+n);
if(n == 0)
error(Eshortstat);
if(!emptystr(d->uid) && strcmp(d->uid, p->user) != 0){
- if(strcmp(up->user, eve) != 0)
+ if(!iseve())
error(Eperm);
- else
- kstrdup(&p->user, d->uid);
+ kstrdup(&p->user, d->uid);
}
/* p->procmode determines default mode for files in /proc */
if(d->mode != ~0UL)
p->procmode = d->mode&0777;
+ qunlock(&p->debug);
poperror();
free(d);
- qunlock(&p->debug);
return n;
}
-
-static long
-procoffset(long offset, char *va, int *np)
+static void
+procclose(Chan *c)
{
- if(offset > 0) {
- offset -= *np;
- if(offset < 0) {
- memmove(va, va+*np+offset, -offset);
- *np = -offset;
+ Segio *sio;
+
+ if((c->flag & COPEN) == 0)
+ return;
+
+ switch(QID(c->qid)){
+ case Qtrace:
+ lock(&tlock);
+ if(topens > 0)
+ topens--;
+ if(topens == 0)
+ proctrace = nil;
+ unlock(&tlock);
+ return;
+ case Qmem:
+ sio = c->aux;
+ if(sio != nil){
+ c->aux = nil;
+ segio(sio, nil, nil, 0, 0, 0);
+ free(sio);
}
- else
- *np = 0;
+ return;
}
- return offset;
}
static int
-procqidwidth(Chan *c)
+procargs(Proc *p, char *buf, int nbuf)
{
- char buf[32];
+ int j, k, m;
+ char *a;
+ int n;
- return sprint(buf, "%lud", c->qid.vers);
+ a = p->args;
+ if(p->setargs){
+ snprint(buf, nbuf, "%s [%s]", p->text, p->args);
+ return strlen(buf);
+ }
+ n = p->nargs;
+ for(j = 0; j < nbuf - 1; j += m){
+ if(n <= 0)
+ break;
+ if(j != 0)
+ buf[j++] = ' ';
+ m = snprint(buf+j, nbuf-j, "%q", a);
+ k = strlen(a) + 1;
+ a += k;
+ n -= k;
+ }
+ return j;
}
-int
-procfdprint(Chan *c, int fd, int w, char *s, int ns)
+static int
+eventsavailable(void *)
{
- int n;
-
- if(w == 0)
- w = procqidwidth(c);
- n = snprint(s, ns, "%3d %.2s %C %4ld (%.16llux %*lud %.2ux) %5ld %8lld %s\n",
- fd,
- &"r w rw"[(c->mode&3)<<1],
- devtab[c->type]->dc, c->dev,
- c->qid.path, w, c->qid.vers, c->qid.type,
- c->iounit, c->offset, c->path->s);
- return n;
+ return tproduced > tconsumed;
}
static int
-procfds(Proc *p, char *va, int count, long offset)
+prochaswaitq(void *x)
{
- Fgrp *f;
Chan *c;
- char buf[256];
- int n, i, w, ww;
- char *a;
-
- /* print to buf to avoid holding fgrp lock while writing to user space */
- if(count > sizeof buf)
- count = sizeof buf;
- a = buf;
-
- qlock(&p->debug);
- f = p->fgrp;
- if(f == nil){
- qunlock(&p->debug);
- return 0;
- }
- lock(f);
- if(waserror()){
- unlock(f);
- qunlock(&p->debug);
- nexterror();
- }
-
- n = readstr(0, a, count, p->dot->path->s);
- n += snprint(a+n, count-n, "\n");
- offset = procoffset(offset, a, &n);
- /* compute width of qid.path */
- w = 0;
- for(i = 0; i <= f->maxfd; i++) {
- c = f->fd[i];
- if(c == nil)
- continue;
- ww = procqidwidth(c);
- if(ww > w)
- w = ww;
- }
- for(i = 0; i <= f->maxfd; i++) {
- c = f->fd[i];
- if(c == nil)
- continue;
- n += procfdprint(c, i, w, a+n, count-n);
- offset = procoffset(offset, a, &n);
- }
- unlock(f);
- qunlock(&p->debug);
- poperror();
-
- /* copy result to user space, now that locks are released */
- memmove(va, buf, n);
-
- return n;
-}
+ Proc *p;
-static void
-procclose(Chan * c)
-{
- if(QID(c->qid) == Qtrace){
- lock(&tlock);
- if(topens > 0)
- topens--;
- if(topens == 0)
- proctrace = nil;
- unlock(&tlock);
- }
- if(QID(c->qid) == Qns && c->aux != 0)
- free(c->aux);
+ c = (Chan *)x;
+ p = proctab(SLOT(c->qid));
+ return p->pid != PID(c->qid) || p->waitq != nil;
}
static void
}
static int
-procargs(Proc *p, char *buf, int nbuf)
+readns1(Chan *c, Proc *p, char *buf, int nbuf)
{
- int j, k, m;
- char *a;
- int n;
+ Pgrp *pg;
+ Mount *t, *cm;
+ Mhead *f, *mh;
+ ulong minid, bestmid;
+ char flag[10], *srv;
+ int i;
- a = p->args;
- if(p->setargs){
- snprint(buf, nbuf, "%s [%s]", p->text, p->args);
- return strlen(buf);
+ pg = p->pgrp;
+ if(pg == nil || p->dot == nil || p->pid != PID(c->qid))
+ error(Eprocdied);
+
+ bestmid = ~0;
+ minid = c->nrock;
+ if(minid == bestmid)
+ return 0;
+
+ rlock(&pg->ns);
+
+ mh = nil;
+ cm = nil;
+ for(i = 0; i < MNTHASH; i++) {
+ for(f = pg->mnthash[i]; f != nil; f = f->hash) {
+ for(t = f->mount; t != nil; t = t->next) {
+ if(t->mountid >= minid && t->mountid < bestmid) {
+ bestmid = t->mountid;
+ cm = t;
+ mh = f;
+ }
+ }
+ }
}
- n = p->nargs;
- for(j = 0; j < nbuf - 1; j += m){
- if(n <= 0)
- break;
- if(j != 0)
- buf[j++] = ' ';
- m = snprint(buf+j, nbuf-j, "%q", a);
- k = strlen(a) + 1;
- a += k;
- n -= k;
+
+ if(bestmid == ~0) {
+ c->nrock = bestmid;
+ i = snprint(buf, nbuf, "cd %s\n", p->dot->path->s);
+ } else {
+ c->nrock = bestmid+1;
+
+ int2flag(cm->mflag, flag);
+ if(strcmp(cm->to->path->s, "#M") == 0){
+ srv = srvname(cm->to->mchan);
+ i = snprint(buf, nbuf, "mount %s %s %s %s\n", flag,
+ srv==nil? cm->to->mchan->path->s : srv,
+ mh->from->path->s, cm->spec? cm->spec : "");
+ free(srv);
+ }else{
+ i = snprint(buf, nbuf, "bind %s %s %s\n", flag,
+ cm->to->path->s, mh->from->path->s);
+ }
}
- return j;
+
+ runlock(&pg->ns);
+
+ return i;
+}
+
+int
+procfdprint(Chan *c, int fd, char *s, int ns)
+{
+ return snprint(s, ns, "%3d %.2s %C %4ld (%.16llux %lud %.2ux) %5ld %8lld %s\n",
+ fd,
+ &"r w rw"[(c->mode&3)<<1],
+ devtab[c->type]->dc, c->dev,
+ c->qid.path, c->qid.vers, c->qid.type,
+ c->iounit, c->offset, c->path->s);
}
static int
-eventsavailable(void *)
+readfd1(Chan *c, Proc *p, char *buf, int nbuf)
{
- return tproduced > tconsumed;
+ Fgrp *fg;
+ int n, i;
+
+ fg = p->fgrp;
+ if(fg == nil || p->dot == nil || p->pid != PID(c->qid))
+ return 0;
+
+ if(c->nrock == 0){
+ c->nrock = 1;
+ return snprint(buf, nbuf, "%s\n", p->dot->path->s);
+ }
+
+ lock(fg);
+ n = 0;
+ for(;;){
+ i = c->nrock-1;
+ if(i < 0 || i > fg->maxfd)
+ break;
+ c->nrock++;
+ if(fg->fd[i] != nil){
+ n = procfdprint(fg->fd[i], i, buf, nbuf);
+ break;
+ }
+ }
+ unlock(fg);
+
+ return n;
+}
+
+/*
+ * userspace can't pass negative file offset for a
+ * 64 bit kernel address, so we use 63 bit and sign
+ * extend to 64 bit.
+ */
+static uintptr
+off2addr(vlong off)
+{
+ off <<= 1;
+ off >>= 1;
+ return off;
}
static long
procread(Chan *c, void *va, long n, vlong off)
{
- /* NSEG*32 was too small for worst cases */
- char *a, flag[10], *sps, *srv, statbuf[NSEG*64];
- int i, j, m, navail, ne, pid, rsize;
- long l;
+ char *a, *sps, statbuf[1024];
+ int i, j, navail, ne, rsize;
+ ulong l;
uchar *rptr;
+ uintptr addr;
ulong offset;
Confmem *cm;
- Mntwalk *mw;
Proc *p;
Segment *sg, *s;
Ureg kur;
a = va;
offset = off;
-
if(c->qid.type & QTDIR)
return devdirread(c, a, n, 0, 0, procgen);
switch(QID(c->qid)){
case Qargs:
- qlock(&p->debug);
- j = procargs(p, up->genbuf, sizeof up->genbuf);
+ eqlock(&p->debug);
+ j = procargs(p, statbuf, sizeof(statbuf));
qunlock(&p->debug);
if(offset >= j)
return 0;
if(offset+n > j)
n = j-offset;
- memmove(a, &up->genbuf[offset], n);
+ statbufread:
+ memmove(a, statbuf+offset, n);
return n;
+
case Qsyscall:
- if(!p->syscalltrace)
- return 0;
- n = readstr(offset, a, n, p->syscalltrace);
- return n;
+ eqlock(&p->debug);
+ if(waserror()){
+ qunlock(&p->debug);
+ nexterror();
+ }
+ if(p->pid != PID(c->qid))
+ error(Eprocdied);
+ j = 0;
+ if(p->syscalltrace != nil)
+ j = readstr(offset, a, n, p->syscalltrace);
+ qunlock(&p->debug);
+ poperror();
+ return j;
case Qmem:
- if(offset < KZERO)
- return procctlmemio(p, offset, n, va, 1);
+ addr = off2addr(off);
+ if(addr < KZERO)
+ return procctlmemio(c, p, addr, va, n, 1);
- if(!iseve())
+ if(!iseve() || poolisoverlap(secrmem, (uchar*)addr, n))
error(Eperm);
/* validate kernel addresses */
- if(offset < (ulong)end) {
- if(offset+n > (ulong)end)
- n = (ulong)end - offset;
- memmove(a, (char*)offset, n);
+ if(addr < (uintptr)end) {
+ if(addr+n > (uintptr)end)
+ n = (uintptr)end - addr;
+ memmove(a, (char*)addr, n);
return n;
}
for(i=0; i<nelem(conf.mem); i++){
cm = &conf.mem[i];
/* klimit-1 because klimit might be zero! */
- if(cm->kbase <= offset && offset <= cm->klimit-1){
- if(offset+n >= cm->klimit-1)
- n = cm->klimit - offset;
- memmove(a, (char*)offset, n);
+ if(cm->kbase <= addr && addr <= cm->klimit-1){
+ if(addr+n >= cm->klimit-1)
+ n = cm->klimit - addr;
+ memmove(a, (char*)addr, n);
return n;
}
}
case Qprofile:
s = p->seg[TSEG];
- if(s == 0 || s->profile == 0)
+ if(s == nil || s->profile == nil)
error("profile is off");
i = (s->top-s->base)>>LRESPROF;
- i *= sizeof(*s->profile);
- if(offset >= i)
+ i *= sizeof(s->profile[0]);
+ if(i < 0 || offset >= i)
return 0;
if(offset+n > i)
n = i - offset;
return n;
case Qnote:
- qlock(&p->debug);
+ eqlock(&p->debug);
if(waserror()){
qunlock(&p->debug);
nexterror();
if(p->nnote == 0)
n = 0;
else {
- m = strlen(p->note[0].msg) + 1;
- if(m > n)
- m = n;
- memmove(va, p->note[0].msg, m);
- ((char*)va)[m-1] = '\0';
- p->nnote--;
+ i = strlen(p->note[0].msg) + 1;
+ if(i < n)
+ n = i;
+ memmove(a, p->note[0].msg, n-1);
+ a[n-1] = '\0';
+ if(--p->nnote == 0)
+ p->notepending = 0;
memmove(p->note, p->note+1, p->nnote*sizeof(Note));
- n = m;
}
- if(p->nnote == 0)
- p->notepending = 0;
poperror();
qunlock(&p->debug);
return n;
rptr = (uchar*)&p->fpsave;
rsize = sizeof(FPsave);
regread:
- if(rptr == 0)
+ if(rptr == nil)
error(Enoreg);
if(offset >= rsize)
return 0;
n = STATSIZE - offset;
sps = p->psstate;
- if(sps == 0)
+ if(sps == nil)
sps = statename[p->state];
+
memset(statbuf, ' ', sizeof statbuf);
- memmove(statbuf+0*KNAMELEN, p->text, strlen(p->text));
- memmove(statbuf+1*KNAMELEN, p->user, strlen(p->user));
- memmove(statbuf+2*KNAMELEN, sps, strlen(sps));
- j = 2*KNAMELEN + 12;
+ readstr(0, statbuf+0*KNAMELEN, KNAMELEN-1, p->text);
+ readstr(0, statbuf+1*KNAMELEN, KNAMELEN-1, p->user);
+ readstr(0, statbuf+2*KNAMELEN, 11, sps);
+ j = 2*KNAMELEN + 12;
for(i = 0; i < 6; i++) {
l = p->time[i];
if(i == TReal)
l = MACHP(0)->ticks - l;
- l = TK2MS(l);
- readnum(0, statbuf+j+NUMSIZE*i, NUMSIZE, l, NUMSIZE);
+ readnum(0, statbuf+j+NUMSIZE*i, NUMSIZE, tk2ms(l), NUMSIZE);
}
- /* ignore stack, which is mostly non-existent */
- l = 0;
- for(i=1; i<NSEG; i++){
- s = p->seg[i];
- if(s)
- l += s->top - s->base;
- }
- readnum(0, statbuf+j+NUMSIZE*6, NUMSIZE, l>>10, NUMSIZE);
+
+ readnum(0, statbuf+j+NUMSIZE*6, NUMSIZE, procpagecount(p)*BY2PG/1024, NUMSIZE);
readnum(0, statbuf+j+NUMSIZE*7, NUMSIZE, p->basepri, NUMSIZE);
readnum(0, statbuf+j+NUMSIZE*8, NUMSIZE, p->priority, NUMSIZE);
- memmove(a, statbuf+offset, n);
- return n;
+ goto statbufread;
case Qsegment:
j = 0;
for(i = 0; i < NSEG; i++) {
sg = p->seg[i];
- if(sg == 0)
+ if(sg == nil)
continue;
- j += sprint(statbuf+j, "%-6s %c%c %.8lux %.8lux %4ld\n",
+ j += sprint(statbuf+j, "%-6s %c%c %8p %8p %4ld\n",
sname[sg->type&SG_TYPE],
sg->type&SG_RONLY ? 'R' : ' ',
sg->profile ? 'P' : ' ',
return 0;
if(offset+n > j)
n = j-offset;
- if(n == 0 && offset == 0)
- exhausted("segments");
- memmove(a, &statbuf[offset], n);
- return n;
+ goto statbufread;
case Qwait:
if(!canqlock(&p->qwaitr))
}
lock(&p->exl);
- if(up == p && p->nchild == 0 && p->waitq == 0) {
+ while(p->waitq == nil && p->pid == PID(c->qid)) {
+ if(up == p && p->nchild == 0) {
+ unlock(&p->exl);
+ error(Enochild);
+ }
unlock(&p->exl);
- error(Enochild);
+ sleep(&p->waitr, prochaswaitq, c);
+ lock(&p->exl);
}
- pid = p->pid;
- while(p->waitq == 0) {
+ if(p->pid != PID(c->qid)){
unlock(&p->exl);
- sleep(&p->waitr, haswaitq, p);
- if(p->pid != pid)
- error(Eprocdied);
- lock(&p->exl);
+ error(Eprocdied);
}
wq = p->waitq;
p->waitq = wq->next;
qunlock(&p->qwaitr);
poperror();
- n = snprint(a, n, "%d %lud %lud %lud %q",
+
+ j = snprint(statbuf, sizeof(statbuf), "%d %lud %lud %lud %q",
wq->w.pid,
wq->w.time[TUser], wq->w.time[TSys], wq->w.time[TReal],
wq->w.msg);
free(wq);
- return n;
+ if(j < n)
+ n = j;
+ offset = 0;
+ goto statbufread;
case Qns:
- qlock(&p->debug);
+ case Qfd:
+ eqlock(&p->debug);
if(waserror()){
qunlock(&p->debug);
nexterror();
}
- if(p->pgrp == nil || p->pid != PID(c->qid))
- error(Eprocdied);
- mw = c->aux;
- if(mw->cddone){
- qunlock(&p->debug);
- poperror();
- return 0;
- }
- mntscan(mw, p);
- if(mw->mh == 0){
- mw->cddone = 1;
- i = snprint(a, n, "cd %s\n", p->dot->path->s);
- qunlock(&p->debug);
- poperror();
- return i;
- }
- int2flag(mw->cm->mflag, flag);
- if(strcmp(mw->cm->to->path->s, "#M") == 0){
- srv = srvname(mw->cm->to->mchan);
- i = snprint(a, n, "mount %s %s %s %s\n", flag,
- srv==nil? mw->cm->to->mchan->path->s : srv,
- mw->mh->from->path->s, mw->cm->spec? mw->cm->spec : "");
- free(srv);
- }else
- i = snprint(a, n, "bind %s %s %s\n", flag,
- mw->cm->to->path->s, mw->mh->from->path->s);
+ if(offset == 0 || offset != c->mrock)
+ c->nrock = c->mrock = 0;
+ do {
+ if(QID(c->qid) == Qns)
+ j = readns1(c, p, statbuf, sizeof(statbuf));
+ else
+ j = readfd1(c, p, statbuf, sizeof(statbuf));
+ if(j == 0)
+ break;
+ c->mrock += j;
+ } while(c->mrock <= offset);
+ i = c->mrock - offset;
qunlock(&p->debug);
poperror();
- return i;
+
+ if(i <= 0 || i > j)
+ return 0;
+ if(i < n)
+ n = i;
+ offset = j - i;
+ goto statbufread;
case Qnoteid:
return readnum(offset, va, n, p->noteid, NUMSIZE);
- case Qfd:
- return procfds(p, va, n, offset);
- }
- error(Egreg);
- return 0; /* not reached */
-}
-
-void
-mntscan(Mntwalk *mw, Proc *p)
-{
- Pgrp *pg;
- Mount *t;
- Mhead *f;
- int nxt, i;
- ulong last, bestmid;
-
- pg = p->pgrp;
- rlock(&pg->ns);
-
- nxt = 0;
- bestmid = ~0;
- last = 0;
- if(mw->mh)
- last = mw->cm->mountid;
+ case Qppid:
+ return readnum(offset, va, n, p->parentpid, NUMSIZE);
- for(i = 0; i < MNTHASH; i++) {
- for(f = pg->mnthash[i]; f; f = f->hash) {
- for(t = f->mount; t; t = t->next) {
- if(mw->mh == 0 ||
- (t->mountid > last && t->mountid < bestmid)) {
- mw->cm = t;
- mw->mh = f;
- bestmid = mw->cm->mountid;
- nxt = 1;
- }
- }
- }
}
- if(nxt == 0)
- mw->mh = 0;
-
- runlock(&pg->ns);
+ error(Egreg);
+ return 0; /* not reached */
}
static long
int id, m;
Proc *p, *t, *et;
char *a, *arg, buf[ERRMAX];
- ulong offset = off;
+ ulong offset;
a = va;
+ offset = off;
if(c->qid.type & QTDIR)
error(Eisdir);
return n;
}
- qlock(&p->debug);
+ eqlock(&p->debug);
if(waserror()){
qunlock(&p->debug);
nexterror();
case Qmem:
if(p->state != Stopped)
error(Ebadctl);
-
- n = procctlmemio(p, offset, n, va, 0);
+ n = procctlmemio(c, p, off2addr(off), va, n, 0);
break;
case Qregs:
n = 0;
else if(offset+n > sizeof(Ureg))
n = sizeof(Ureg) - offset;
- if(p->dbgreg == 0)
+ if(p->dbgreg == nil)
error(Enoreg);
setregisters(p->dbgreg, (char*)(p->dbgreg)+offset, va, n);
break;
error("note not posted");
break;
case Qnoteid:
+ if(p->kp)
+ error(Eperm);
id = atoi(a);
+ if(id <= 0)
+ error(Ebadarg);
if(id == p->pid) {
p->noteid = id;
break;
}
t = proctab(0);
for(et = t+conf.nproc; t < et; t++) {
- if(t->state == Dead)
+ if(t->state == Dead || t->kp)
continue;
if(id == t->noteid) {
+ nonone(t);
if(strcmp(p->user, t->user) != 0)
error(Eperm);
p->noteid = id;
error(Ebadarg);
break;
default:
- pprint("unknown qid in procwrite\n");
+ print("unknown qid in procwrite\n");
error(Egreg);
}
poperror();
Segment *s;
s = p->seg[TSEG];
- if(s == 0)
+ if(s == nil)
error(Enonexist);
if(p->state==Dead)
error(Eprocdied);
- lock(s);
i = s->image;
- if(i == 0) {
- unlock(s);
+ if(i == nil)
error(Eprocdied);
- }
- unlock(s);
lock(i);
if(waserror()) {
unlock(i);
nexterror();
}
-
+
tc = i->c;
- if(tc == 0)
+ if(tc == nil)
error(Eprocdied);
- if(incref(tc) == 1 || (tc->flag&COPEN) == 0 || tc->mode!=OREAD) {
+ if(incref(tc) == 1 || (tc->flag&COPEN) == 0 || tc->mode != OREAD) {
cclose(tc);
error(Eprocdied);
}
- if(p->pid != PID(c->qid))
+ if(p->pid != PID(c->qid)) {
+ cclose(tc);
error(Eprocdied);
+ }
unlock(i);
poperror();
{
int pid;
- if(p->pdbg)
+ if(p->pdbg != nil)
error(Einuse);
if(procstopped(p) || p->state == Broken)
return;
-
+ pid = p->pid;
+ if(pid == 0)
+ error(Eprocdied);
if(ctl != 0)
p->procctl = ctl;
p->pdbg = up;
- pid = p->pid;
qunlock(&p->debug);
up->psstate = "Stopwait";
if(waserror()) {
- p->pdbg = 0;
qlock(&p->debug);
+ p->pdbg = nil;
nexterror();
}
sleep(&up->sleep, procstopped, p);
error(Eprocdied);
}
-static void
-procctlcloseone(Proc *p, Fgrp *f, int fd)
-{
- Chan *c;
-
- c = f->fd[fd];
- if(c == nil)
- return;
- f->fd[fd] = nil;
- unlock(f);
- qunlock(&p->debug);
- cclose(c);
- qlock(&p->debug);
- lock(f);
-}
-
void
procctlclosefiles(Proc *p, int all, int fd)
{
- int i;
Fgrp *f;
+ Chan *c;
+ if(fd < 0)
+ error(Ebadfd);
f = p->fgrp;
if(f == nil)
error(Eprocdied);
+ incref(f);
lock(f);
- f->ref++;
- if(all)
- for(i = 0; i < f->maxfd; i++)
- procctlcloseone(p, f, i);
- else
- procctlcloseone(p, f, fd);
+ while(fd <= f->maxfd){
+ c = f->fd[fd];
+ if(c != nil){
+ f->fd[fd] = nil;
+ unlock(f);
+ qunlock(&p->debug);
+ cclose(c);
+ qlock(&p->debug);
+ lock(f);
+ }
+ if(!all)
+ break;
+ fd++;
+ }
unlock(f);
closefgrp(f);
}
break;
case CMprofile:
s = p->seg[TSEG];
- if(s == 0 || (s->type&SG_TYPE) != SG_TEXT)
+ if(s == nil || (s->type&SG_TYPE) != SG_TEXT)
error(Ebadctl);
- if(s->profile != 0)
+ if(s->profile != nil)
free(s->profile);
npc = (s->top-s->base)>>LRESPROF;
s->profile = malloc(npc*sizeof(*s->profile));
- if(s->profile == 0)
+ if(s->profile == nil)
error(Enomem);
break;
case CMstart:
error("args");
}
break;
+ case CMinterrupt:
+ postnote(p, 0, nil, NUser);
+ break;
+ case CMnointerrupt:
+ if(p->nnote == 0)
+ p->notepending = 0;
+ else
+ error("notes pending");
+ break;
/* real time */
case CMperiod:
if(p->edf == nil)
p->edf->flags |= Sendnotes;
break;
case CMadmit:
- if(p->edf == 0)
+ if(p->edf == nil)
error("edf params");
if(e = edfadmit(p))
error(e);
p->edf->flags |= Extratime;
break;
case CMexpel:
- if(p->edf)
+ if(p->edf != nil)
edfstop(p);
break;
case CMevent:
pt = proctrace;
- if(up->trace && pt)
+ if(up->trace && pt != nil)
pt(up, SUser, 0);
break;
}
int
procstopped(void *a)
{
- Proc *p = a;
- return p->state == Stopped;
+ return ((Proc*)a)->state == Stopped;
}
-int
-procctlmemio(Proc *p, ulong offset, int n, void *va, int read)
+long
+procctlmemio(Chan *c, Proc *p, uintptr offset, void *a, long n, int read)
{
- KMap *k;
- Pte *pte;
- Page *pg;
+ Segio *sio;
Segment *s;
- ulong soff, l;
- char *a = va, *b;
-
- for(;;) {
- s = seg(p, offset, 1);
- if(s == 0)
- error(Ebadarg);
-
- if(offset+n >= s->top)
- n = s->top-offset;
-
- if(!read && (s->type&SG_TYPE) == SG_TEXT)
- s = txt2data(p, s);
+ int i;
- s->steal++;
- soff = offset-s->base;
- if(waserror()) {
- s->steal--;
- nexterror();
- }
- if(fixfault(s, offset, read, 0) == 0)
+ s = seg(p, offset, 0);
+ if(s == nil)
+ error(Ebadarg);
+ eqlock(&p->seglock);
+ if(waserror()) {
+ qunlock(&p->seglock);
+ nexterror();
+ }
+ sio = c->aux;
+ if(sio == nil){
+ sio = smalloc(sizeof(Segio));
+ c->aux = sio;
+ }
+ for(i = 0; i < NSEG; i++) {
+ if(p->seg[i] == s)
break;
- poperror();
- s->steal--;
}
+ if(i == NSEG)
+ error(Egreg); /* segment gone */
+ eqlock(s);
+ if(waserror()){
+ qunlock(s);
+ nexterror();
+ }
+ if(!read && (s->type&SG_TYPE) == SG_TEXT) {
+ s = txt2data(s);
+ p->seg[i] = s;
+ }
+ offset -= s->base;
+ incref(s); /* for us while we copy */
+ qunlock(s);
poperror();
- pte = s->map[soff/PTEMAPMEM];
- if(pte == 0)
- panic("procctlmemio");
- pg = pte->pages[(soff&(PTEMAPMEM-1))/BY2PG];
- if(pagedout(pg))
- panic("procctlmemio1");
-
- l = BY2PG - (offset&(BY2PG-1));
- if(n > l)
- n = l;
-
- k = kmap(pg);
+ qunlock(&p->seglock);
+ poperror();
+
if(waserror()) {
- s->steal--;
- kunmap(k);
+ putseg(s);
nexterror();
}
- b = (char*)VA(k);
- b += offset&(BY2PG-1);
- if(read == 1)
- memmove(a, b, n); /* This can fault */
- else
- memmove(b, a, n);
- kunmap(k);
+ n = segio(sio, s, a, n, offset, read);
+ putseg(s);
poperror();
- /* Ensure the process sees text page changes */
- if(s->flushme)
- memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
-
- s->steal--;
-
- if(read == 0)
+ if(!read)
p->newtlb = 1;
return n;
}
-
-Segment*
-txt2data(Proc *p, Segment *s)
-{
- int i;
- Segment *ps;
-
- ps = newseg(SG_DATA, s->base, s->size);
- ps->image = s->image;
- incref(ps->image);
- ps->fstart = s->fstart;
- ps->flen = s->flen;
- ps->flushme = 1;
-
- qlock(&p->seglock);
- for(i = 0; i < NSEG; i++)
- if(p->seg[i] == s)
- break;
- if(i == NSEG)
- panic("segment gone");
-
- qunlock(&s->lk);
- putseg(s);
- qlock(&ps->lk);
- p->seg[i] = ps;
- qunlock(&p->seglock);
-
- return ps;
-}
-
-Segment*
-data2txt(Segment *s)
-{
- Segment *ps;
-
- ps = newseg(SG_TEXT, s->base, s->size);
- ps->image = s->image;
- incref(ps->image);
- ps->fstart = s->fstart;
- ps->flen = s->flen;
- ps->flushme = 1;
-
- return ps;
-}