ref: f6da1ab12d14fe4db7a76f390d6dfc85de660f1c
parent: 4fd46455350c3e29718f8fdd6d709f3c72b4abb4
author: halfwit <michaelmisch1985@gmail.com>
date: Thu Nov 20 18:57:42 EST 2025
Much more progress, just CD seems broken at the moment
--- a/TODO
+++ b/TODO
@@ -6,7 +6,7 @@
- [ ] Use ScreenCaptureKit to get at the video/audio. Handle resizes the other direction
- [ ] define the gui interface
- [ ] Fully fledged note handling
- - [ ] up->parent integration into /proc
+ - [x] up->parent integration into /proc
Kernel space needs:
- [x] devcmd - #C: OS(1) commands, we already run on host
@@ -21,5 +21,4 @@
- [x] devssl - #D: needed, ssl
- [x] devtls - #a: needed, tls
- [ ] devproc - #p: needed, /proc, overlay any existing
- - [ ] devbin - #9: needed, just a path that can use PLAN9 environment variable
- [x] devtab - # meta: needed add/remove any devices that we add/remove, from here as well
--- a/include/proc.h
+++ b/include/proc.h
@@ -1,4 +1,3 @@
extern void step(void);
int loadtext(char *, int, char **);
-void inittos(void);
void resetvfp(void);
\ No newline at end of file
--- a/kern/Makefile
+++ b/kern/Makefile
@@ -19,6 +19,7 @@
devip.$O\
devmnt.$O\
devpipe.$O\
+ devproc.$O\
devroot.$O\
devssl.$O\
devtab.$O\
--- a/kern/arm.c
+++ b/kern/arm.c
@@ -484,7 +484,37 @@
step(void)
{u32int instr;
+ char *state;
Segment *seg;
+
+ switch(up->procctl) {+ case Proc_traceme:
+ //if(up->nnote == 0)
+ // return;
+ /* No break */
+ case Proc_stopme:
+ up->procctl = 0;
+ //state = up->psstate;
+ //up->psstate = statename[Stopped];
+ /* free a waiting debugger */
+ //spllo();
+ //qlock(&up->debug);
+ //if(up->pdbg != nil) {+ // wakeup(&up->pdbg->sleep);
+ // up->pdbg = nil;
+ //}
+ //qunlock(&up->debug);
+ //splhi();
+ //up->state = Stopped;
+ //sched();
+ //up->psstate = state;
+ return;
+ case Proc_exitme:
+ pexit("Killed", 1);+ case Proc_exitbig:
+ pprint("Killed: Insufficient physical memory\n");+ pexit("Killed: Insufficient physical memory", 1);+ }
instr = *(u32int*) vaddr(up->R[15], 4, &seg);
segunlock(seg);
--- a/kern/await.c
+++ b/kern/await.c
@@ -1,7 +1,12 @@
+#include "u.h"
+#include "lib.h"
+#include "dat.h"
+#include "fns.h"
+#include "error.h"
+#include "user.h"
+#include "sys.h"
+#include "proc.h"
-#include <u.h>
-#include <libc.h>
-
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
@@ -81,56 +86,8 @@
return 0;
}
-static int
-_await(int pid4, char *str, int n, int opt)
-{- int pid, status, cd;
- struct rusage ru;
- char buf[128], tmp[64];
- ulong u, s;
-
- for(;;){- /* On Linux, pid==-1 means anyone; on SunOS, it's pid==0. */
- if(pid4 == -1)
- pid = wait3(&status, opt, &ru);
- else
- pid = wait4(pid4, &status, opt, &ru);
- if(pid <= 0)
- return -1;
- u = ru.ru_utime.tv_sec*1000+((ru.ru_utime.tv_usec+500)/1000);
- s = ru.ru_stime.tv_sec*1000+((ru.ru_stime.tv_usec+500)/1000);
- if(WIFEXITED(status)){- status = WEXITSTATUS(status);
- if(status)
- snprint(buf, sizeof buf, "%d %lud %lud %lud %d", pid, u, s, u+s, status);
- else
- snprint(buf, sizeof buf, "%d %lud %lud %lud ''", pid, u, s, u+s, status);
- strecpy(str, str+n, buf);
- return strlen(str);
- }
- if(WIFSIGNALED(status)){- cd = WCOREDUMP(status);
- snprint(buf, sizeof buf, "%d %lud %lud %lud 'signal: %s%s'", pid, u, s, u+s, _p9sigstr(WTERMSIG(status), tmp), cd ? " (core dumped)" : "");
- strecpy(str, str+n, buf);
- return strlen(str);
- }
- }
-}
-
int
-await(char *str, int n)
+await(char *p, int n)
{- return _await(-1, str, n, 0);
-}
-
-int
-awaitnohang(char *str, int n)
-{- return _await(-1, str, n, WNOHANG);
-}
-
-int
-awaitfor(int pid, char *str, int n)
-{- return _await(pid, str, n, 0);
+ return osawait(up, p, n);
}
--- a/kern/chan.c
+++ b/kern/chan.c
@@ -1469,7 +1469,6 @@
}
/* create failed */
- cclose(cnew);
putmhead(m);
if(omode & OEXCL)
nexterror();
--- a/kern/dat.h
+++ b/kern/dat.h
@@ -405,11 +405,20 @@
enum
{+ Dead = 0,
+ Moribund,
+ Ready,
Running,
- Rendezvous,
Wakeme,
- Dead,
+ Broken,
Stopped,
+ Rendezvous,
+
+ Proc_stopme = 1, /* devproc requests */
+ Proc_exitme,
+ Proc_traceme,
+ Proc_exitbig,
+ Proc_tracesyscall,
};
struct Fd
@@ -475,7 +484,9 @@
Proc *qnext;
Proc *parent;
+ Proc *child;
int nchild;
+ int procctl;
void (*fn)(void*);
void *arg;
--- a/kern/devproc.c
+++ b/kern/devproc.c
@@ -14,7 +14,6 @@
Qargs,
Qctl,
Qfd,
- Qmem,
Qnote,
Qnoteid,
Qnotepg,
@@ -21,14 +20,11 @@
Qns,
Qppid,
Qproc,
- Qregs,
Qsegment,
Qstatus,
- Qtext,
Qwait,
Qprofile,
Qsyscall,
- Qwatchpt,
};
enum
@@ -48,7 +44,6 @@
CMstartsyscall,
CMstop,
CMwaitstop,
- CMwired,
CMtrace,
CMinterrupt,
CMnointerrupt,
@@ -84,7 +79,6 @@
"args", {Qargs}, 0, 0660, "ctl", {Qctl}, 0, 0000, "fd", {Qfd}, 0, 0444,- "mem", {Qmem}, 0, 0000, "note", {Qnote}, 0, 0000, "noteid", {Qnoteid}, 0, 0664, "notepg", {Qnotepg}, 0, 0000,@@ -91,14 +85,11 @@
"ns", {Qns}, 0, 0444, "ppid", {Qppid}, 0, 0444, "proc", {Qproc}, 0, 0400,- "regs", {Qregs}, REGSIZE, 0000, "segment", {Qsegment}, 0, 0444, "status", {Qstatus}, STATSIZE, 0444,- "text", {Qtext}, 0, 0000, "wait", {Qwait}, 0, 0400, "profile", {Qprofile}, 0, 0400, "syscall", {Qsyscall}, 0, 0400, - "watchpt", {Qwatchpt}, 0, 0600,};
static
@@ -118,7 +109,6 @@
CMstartsyscall, "startsyscall", 1,
CMstop, "stop", 1,
CMwaitstop, "waitstop", 1,
- CMwired, "wired", 2,
CMtrace, "trace", 0,
CMinterrupt, "interrupt", 1,
CMnointerrupt, "nointerrupt", 1,
@@ -127,6 +117,87 @@
/* Segment type from dat.h */
static char *sname[]={ "Text", "Data", "Bss", "Stack", "Shared", "Phys", "Fixed", "Sticky" };+static void
+nonone(Proc *p)
+{+ if(p == up)
+ return;
+ if(strcmp(up->user, "none") != 0)
+ return;
+ if(iseve())
+ return;
+ error(Eperm);
+}
+
+static void
+procstopwait(Proc *p, int ctl)
+{+ char *state;
+ int pid;
+/*
+ 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;
+ if(p == up)
+ return;
+ p->pdbg = up;
+ qunlock(&p->debug);
+ state = up->psstate;
+ up->psstate = "Stopwait";
+ if(waserror()) {+ up->psstate = state;
+ qlock(&p->debug);
+ if(p->pdbg == up)
+ p->pdbg = nil;
+ nexterror();
+ }
+ sleep(&up->sleep, procstopped, p);
+ poperror();
+ up->psstate = state;
+ qlock(&p->debug);
+ if(p->pid != pid)
+ error(Eprocdied);
+*/
+}
+
+static void
+procctlclosefiles(Proc *p, int all, int fd)
+{+ Fgrp *f;
+ Chan *c;
+
+ if(fd < 0)
+ error(Ebadfd);
+ f = p->fgrp;
+ if(f == nil)
+ error(Eprocdied);
+
+ incref(f);
+ lock(f);
+ 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);
+}
+
static int
procgen(Chan *c, char *name, Dirtab *tab, int nd, int s, Dir *dp)
{@@ -135,7 +206,6 @@
char *ename;
Segment *q;
ulong pid, path, perm, len;
-
if(s == DEVDOTDOT){mkqid(&qid, Qdir, 0, QTDIR);
devdir(c, qid, "#p", 0, eve, 0555, dp);
@@ -155,7 +225,7 @@
pid = strtol(name, &ename, 10);
if(pid==0 || ename[0]!='\0')
return -1;
- s = procindex(pid);
+ s = pid;
if(s < 0)
return -1;
}
@@ -203,26 +273,105 @@
len = tab->length;
switch(QID(c->qid)) {case Qwait:
- len = p->nwait; /* incorrect size, but >0 means there's something to read */
+ // len = p->nwait; /* incorrect size, but >0 means there's something to read */
break;
case Qprofile:
- q = p->seg[TSEG];
- if(q != nil && q->profile != nil) {- len = (q->size-q->start)>>LRESPROF;
- len *= sizeof(*q->profile);
- }
+ // q = p->seg[TSEG];
+ // if(q != nil && q->profile != nil) {+ // len = (q->size-q->start)>>LRESPROF;
+ // len *= sizeof(*q->profile);
+ // }
break;
- case Qwatchpt:
- len = lenwatchpt(p);
- break;
}
-
+len = 0;
mkqid(&qid, path|tab->qid.path, c->qid.vers, QTFILE);
devdir(c, qid, tab->name, len, p->user, perm, dp);
return 1;
}
+
static void
+int2flag(int flag, char *s)
+{+ if(flag == 0){+ *s = '\0';
+ return;
+ }
+ *s++ = '-';
+ if(flag & MAFTER)
+ *s++ = 'a';
+ if(flag & MBEFORE)
+ *s++ = 'b';
+ if(flag & MCREATE)
+ *s++ = 'c';
+ if(flag & MCACHE)
+ *s++ = 'C';
+ *s = '\0';
+}
+
+static int
+readns1(Chan *c, Proc *p, char *buf, int nbuf)
+{+ Pgrp *pg;
+ Mount *t, *cm;
+ Mhead *f, *mh;
+ ulong minid, bestmid;
+ char flag[10], *srv;
+ int i;
+
+ 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) {+ rlock(&f->lock);
+ for(t = f->mount; t != nil; t = t->next) {+ if(t->mountid >= minid && t->mountid < bestmid) {+ bestmid = t->mountid;
+ cm = t;
+ mh = f;
+ }
+ }
+ runlock(&f->lock);
+ }
+ }
+
+ if(bestmid == ~0) {+ c->nrock = bestmid;
+ i = snprint(buf, nbuf, "cd %q\n", p->dot->path->s);
+ } else {+ c->nrock = bestmid+1;
+
+ int2flag(cm->mflag, flag);
+ if(strcmp(cm->to->path->s, "#M") == 0){+ //srv = cm->to->mchan->srvname;
+ if(srv == nil)
+ srv = cm->to->mchan->path->s;
+ i = snprint(buf, nbuf, *cm->spec?
+ "mount %s %q %q %q\n": "mount %s %q %q\n", flag,
+ srv, mh->from->path->s, cm->spec);
+ }else{+ i = snprint(buf, nbuf, "bind %s %q %q\n", flag,
+ cm->to->path->s, mh->from->path->s);
+ }
+ }
+
+ runlock(&pg->ns);
+
+ return i;
+}
+
+static void
procinit(void)
{return;
@@ -231,7 +380,13 @@
static Chan*
procattach(char *spec)
{- return devattach('p', spec);+ Chan *c;
+
+ c = devattach('p', spec);+ c->qid.path = Qdir;
+ c->qid.vers = 0;
+ c->qid.type = QTDIR;
+ return c;
}
static Walkqid*
@@ -254,23 +409,23 @@
if(QID(c->qid) == Qtrace){if (omode0 != OREAD || !iseve())
error(Eperm);
- lock(&tlock);
- if (waserror()){- topens--;
- unlock(&tlock);
- nexterror();
- }
- if (topens++ > 0)
- error("already open");- if (tevents == nil){- tevents = (Traceevent*)malloc(sizeof(Traceevent) * Nevents);
- if(tevents == nil)
- error(Enomem);
- tproduced = tconsumed = 0;
- }
- proctrace = _proctrace;
- unlock(&tlock);
- poperror();
+ // lock(&tlock);
+ // if (waserror()){+ // topens--;
+ // unlock(&tlock);
+ // nexterror();
+ // }
+ // if (topens++ > 0)
+ // error("already open");+ // if (tevents == nil){+ // tevents = (Traceevent*)malloc(sizeof(Traceevent) * Nevents);
+ // if(tevents == nil)
+ // error(Enomem);
+ // tproduced = tconsumed = 0;
+ // }
+ // proctrace = _proctrace;
+ // unlock(&tlock);
+ // poperror();
c->mode = openmode(omode0);
c->flag |= COPEN;
@@ -279,7 +434,7 @@
}
p = proctab(SLOT(c->qid));
- eqlock(&p->debug);
+ qlock(&p->debug);
if(waserror()){qunlock(&p->debug);
nexterror();
@@ -291,16 +446,6 @@
omode = openmode(omode0);
switch(QID(c->qid)){- case Qtext:
- if(omode != OREAD)
- error(Eperm);
- nonone(p);
- qunlock(&p->debug);
- poperror();
- tc = proctext(c, p);
- tc->offset = 0;
- cclose(c);
- return tc;
case Qstatus:
case Qppid:
@@ -324,16 +469,13 @@
break;
case Qnotepg:
- if(p->kp || omode != OWRITE)
- error(Eperm);
- pid = p->noteid;
+ //if(p->kp || omode != OWRITE)
+ // error(Eperm);
+ //pid = p->noteid;
break;
- case Qmem:
- case Qregs:
case Qprofile:
case Qsyscall:
- case Qwatchpt:
break;
default:
@@ -353,13 +495,6 @@
nexterror();
}
- switch(QID(c->qid)){- case Qwatchpt:
- if((omode0 & OTRUNC) != 0)
- clearwatchpt(p);
- break;
- }
-
poperror();
qunlock(&p->debug);
poperror();
@@ -382,27 +517,27 @@
offset = off;
if(c->qid.type & QTDIR)
return devdirread(c, va, n, 0, 0, procgen);
-
+
if(QID(c->qid) == Qtrace){- int navail, ne;
+ // int navail, ne;
- if(!eventsavailable(nil))
- return 0;
+ // if(!eventsavailable(nil))
+ // return 0;
- rptr = (uchar*)va;
- navail = tproduced - tconsumed;
- if(navail > n / sizeof(Traceevent))
- navail = n / sizeof(Traceevent);
- while(navail > 0) {- ne = ((tconsumed & Emask) + navail > Nevents)?
- Nevents - (tconsumed & Emask): navail;
- memmove(rptr, &tevents[tconsumed & Emask],
- ne * sizeof(Traceevent));
+ // rptr = (uchar*)va;
+ // navail = tproduced - tconsumed;
+ // if(navail > n / sizeof(Traceevent))
+ // navail = n / sizeof(Traceevent);
+ // while(navail > 0) {+ // ne = ((tconsumed & Emask) + navail > Nevents)?
+ // Nevents - (tconsumed & Emask): navail;
+ // memmove(rptr, &tevents[tconsumed & Emask],
+ // ne * sizeof(Traceevent));
- tconsumed += ne;
- rptr += ne * sizeof(Traceevent);
- navail -= ne;
- }
+ // tconsumed += ne;
+ // rptr += ne * sizeof(Traceevent);
+ // navail -= ne;
+ // }
return rptr - (uchar*)va;
}
@@ -411,54 +546,28 @@
error(Eprocdied);
switch(QID(c->qid)){- case Qmem:
- addr = off2addr(off);
- if(addr < KZERO)
- return procctlmemio(c, p, addr, va, n, 1);
-
- if(!iseve() || poolisoverlap(secrmem, (uchar*)addr, n))
- error(Eperm);
-
- // validate kernel addresses
- if(addr < (uintptr)end) {- if(addr+n > (uintptr)end)
- n = (uintptr)end - addr;
- memmove(va, (char*)addr, n);
- return n;
- }
- for(i=0; i<nelem(conf.mem); i++){- Confmem *cm = &conf.mem[i];
- // klimit-1 because klimit might be zero!
- if(cm->kbase <= addr && addr <= cm->klimit-1){- if(addr+n >= cm->klimit-1)
- n = cm->klimit - addr;
- memmove(va, (char*)addr, n);
- return n;
- }
- }
-
- error(Ebadarg);
-
case Qctl:
return readnum(offset, va, n, p->pid, NUMSIZE);
case Qnoteid:
- return readnum(offset, va, n, p->noteid, NUMSIZE);
+ return readnum(offset, va, n, p->notein, NUMSIZE);
case Qppid:
- return readnum(offset, va, n, p->parentpid, NUMSIZE);
+ if(!p->parent)
+ return readnum(offset, va, n, 0, NUMSIZE);
+ return readnum(offset, va, n, p->parent->pid, NUMSIZE);
case Qprofile:
- s = p->seg[TSEG];
- if(s == nil || s->profile == nil)
- error("profile is off");- i = (s->size-s->start)>>LRESPROF;
- i *= sizeof(s->profile[0]);
- if(i < 0 || offset >= i)
- return 0;
- if(offset+n > i)
- n = i - offset;
- memmove(va, ((char*)s->profile)+offset, n);
+ // s = p->seg[TSEG];
+ // if(s == nil || s->profile == nil)
+ // error("profile is off");+ // i = (s->size-s->start)>>LRESPROF;
+ // i *= sizeof(s->profile[0]);
+ // if(i < 0 || offset >= i)
+ // return 0;
+ // if(offset+n > i)
+ // n = i - offset;
+ // memmove(va, ((char*)s->profile)+offset, n);
return n;
case Qproc:
@@ -474,15 +583,10 @@
memmove(va, rptr+offset, n);
return n;
- case Qregs:
- rptr = (uchar*)p->dbgreg;
- rsize = REGSIZE;
- goto regread;
-
case Qstatus:
- sps = p->psstate;
- if(sps == nil)
- sps = statename[p->state];
+ // sps = p->psstate;
+ // if(sps == nil)
+ // sps = statename[p->state];
/* NOTE: We don't have any p->time tracking
this is handled by the pthreads/windows
j = snprint(statbuf, sizeof(statbuf),
@@ -518,52 +622,52 @@
"%-6s %c%c %8p %8p %4ld\n",
sname[s->type&SG_TYPE],
s->type&SG_FAULT ? 'F' : (s->type&SG_RONLY ? 'R' : ' '),
- s->profile ? 'P' : ' ',
+ ' ', //s->profile ? 'P' : ' ',
s->start, s->size, s->ref);
}
goto statbufread;
case Qwait:
- if(!canqlock(&p->qwaitr))
- error(Einuse);
+ // if(!canqlock(&p->qwaitr))
+ // error(Einuse);
- if(waserror()) {- qunlock(&p->qwaitr);
- nexterror();
- }
+ // if(waserror()) {+ // qunlock(&p->qwaitr);
+ // nexterror();
+ // }
- lock(&p->exl);
- while(p->waitq == nil && p->pid == PID(c->qid)) {- if(up == p && p->nchild == 0) {- unlock(&p->exl);
- error(Enochild);
- }
- unlock(&p->exl);
- sleep(&p->waitr, prochaswaitq, c);
- lock(&p->exl);
- }
- if(p->pid != PID(c->qid)){- unlock(&p->exl);
- error(Eprocdied);
- }
- wq = p->waitq;
- p->waitq = wq->next;
- p->nwait--;
- unlock(&p->exl);
+ // lock(&p->exl);
+ // while(p->waitq == nil && p->pid == PID(c->qid)) {+ // if(up == p && p->nchild == 0) {+ // unlock(&p->exl);
+ // error(Enochild);
+ // }
+ // unlock(&p->exl);
+ // sleep(&p->waitr, prochaswaitq, c);
+ // lock(&p->exl);
+ // }
+ // if(p->pid != PID(c->qid)){+ // unlock(&p->exl);
+ // error(Eprocdied);
+ // }
+ // wq = p->waitq;
+ // p->waitq = wq->next;
+ // p->nwait--;
+ // unlock(&p->exl);
- qunlock(&p->qwaitr);
- poperror();
+ // qunlock(&p->qwaitr);
+ // poperror();
- 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);
- offset = 0;
+ // 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);
+ // offset = 0;
goto statbufread;
}
- eqlock(&p->debug);
+ qlock(&p->debug);
if(waserror()){qunlock(&p->debug);
nexterror();
@@ -579,8 +683,8 @@
do {if(QID(c->qid) == Qns)
j = readns1(c, p, statbuf, sizeof(statbuf));
- else
- j = readfd1(c, p, statbuf, sizeof(statbuf));
+ // else
+ // j = readfd1(c, p, statbuf, sizeof(statbuf));
if(j == 0)
break;
c->mrock += j;
@@ -596,43 +700,37 @@
goto statbufread;
case Qargs:
- j = procargs(p, statbuf, sizeof(statbuf));
+ // j = procargs(p, statbuf, sizeof(statbuf));
qunlock(&p->debug);
poperror();
goto statbufread;
- case Qwatchpt:
- j = readwatchpt(p, statbuf, sizeof(statbuf));
- qunlock(&p->debug);
- poperror();
- goto statbufread;
-
case Qsyscall:
- if(p->syscalltrace != nil)
- n = readstr(offset, va, n, p->syscalltrace);
- else
- n = 0;
+ // if(p->syscalltrace != nil)
+ // n = readstr(offset, va, n, p->syscalltrace);
+ // else
+ // n = 0;
break;
case Qnote:
- if(n < 1) /* must accept at least the '\0' */
- error(Etoosmall);
- if(p->nnote == 0)
- n = 0;
- else {- assert(p->note[0] != nil);
- i = strlen(p->note[0]->msg) + 1;
- if(i < n)
- n = i;
- memmove(va, p->note[0]->msg, n-1);
- ((char*)va)[n-1] = '\0';
- freenote(p->note[0]);
- if(--p->nnote == 0)
- p->notepending = 0;
- else
- memmove(&p->note[0], &p->note[1], p->nnote*sizeof(Note*));
- p->note[p->nnote] = nil;
- }
+ // if(n < 1) /* must accept at least the '\0' */
+ // error(Etoosmall);
+ // if(p->nnote == 0)
+ // n = 0;
+ // else {+ // assert(p->note[0] != nil);
+ // i = strlen(p->note[0]->msg) + 1;
+ // if(i < n)
+ // n = i;
+ // memmove(va, p->note[0]->msg, n-1);
+ // ((char*)va)[n-1] = '\0';
+ // freenote(p->note[0]);
+ // if(--p->nnote == 0)
+ // p->notepending = 0;
+ // else
+ // memmove(&p->note[0], &p->note[1], p->nnote*sizeof(Note*));
+ // p->note[p->nnote] = nil;
+ // }
break;
default:
@@ -663,11 +761,16 @@
error(Etoobig);
memmove(buf, va, n);
buf[n] = 0;
- postnotepg(NOTEID(c->qid), buf, NUser);
+ // postnotepg(NOTEID(c->qid), buf, NUser);
return n;
}
p = proctab(SLOT(c->qid));
+ qlock(&p->debug);
+ if(waserror()){+ qunlock(&p->debug);
+ nexterror();
+ }
if(p->pid != PID(c->qid))
error(Eprocdied);
@@ -677,26 +780,11 @@
error(Etoobig);
memmove(buf, va, n);
buf[n] = 0;
- kstrdup(&p->args, buf);
- p->nargs = 0;
- p->setargs = 1;
+ // kstrdup(&p->args, buf);
+ // p->nargs = 0;
+ // p->setargs = 1;
break;
- case Qmem:
- if(p->state != Stopped)
- error(Ebadctl);
- n = procctlmemio(c, p, off2addr(off), va, n, 0);
- break;
-
- case Qregs:
- if(offset >= REGSIZE)
- n = 0;
- else if(offset+n > REGSIZE)
- n = REGSIZE - offset;
- if(p->dbgreg == nil)
- error(Enoreg);
- setregisters(p->dbgreg, (char*)(p->dbgreg)+offset, va, n);
- break;
case Qctl:
procctlreq(p, va, n);
break;
@@ -715,7 +803,7 @@
error(Etoobig);
memmove(buf, va, n);
buf[n] = 0;
- changenoteid(p, atoi(buf));
+ // changenoteid(p, atoi(buf));
break;
default:
@@ -723,13 +811,36 @@
error(Egreg);
}
poperror();
+ qunlock(&p->debug);
return n;
}
+/*
+ * called with p->debug locked.
+ */
+void
+killproc(Proc *p, int ctl)
+{+ int new;
+
+ if(p->pid == 0 || p->kp)
+ return;
+ if(ctl != 0)
+ p->procctl = ctl;
+ new = up->notein + 1;
+ if((new - up->noteout) % NNOTE == 0)
+ return;
+ strncpy(up->notes[up->notein % NNOTE], "sys: killed", ERRMAX - 1);
+ up->notein = new;
+ //if(p->state == Stopped)
+ // ready(p);
+}
+
+
static void
procclose(Chan *c)
{- Segio *sio;
+ //Segio *sio;
if((c->flag & COPEN) == 0)
return;
@@ -736,21 +847,13 @@
switch(QID(c->qid)){case Qtrace:
- lock(&tlock);
- if(topens > 0)
- topens--;
- if(topens == 0)
- proctrace = nil;
- unlock(&tlock);
+ // 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);
- }
- return;
}
}
@@ -779,7 +882,7 @@
error(Eshortstat);
p = proctab(SLOT(c->qid));
- eqlock(&p->debug);
+ qlock(&p->debug);
if(waserror()){qunlock(&p->debug);
nexterror();
@@ -843,75 +946,76 @@
procctlclosefiles(p, 1, 0);
break;
case CMhang:
- p->hang = 1;
+ // p->hang = 1;
break;
case CMkill:
- killproc(p, Proc_exitme);
+ // killproc(p, Proc_exitme);
break;
case CMnohang:
- p->hang = 0;
+ // p->hang = 0;
break;
case CMnoswap:
- p->noswap = 1;
+ // p->noswap = 1;
break;
+// TODO: procpriority --> osprocpriority call
case CMpri:
- pri = atoi(cb->f[1]);
- if(pri > PriNormal && !iseve())
- error(Eperm);
- procpriority(p, pri, 0);
+ // pri = atoi(cb->f[1]);
+ // if(pri > PriNormal && !iseve())
+ // error(Eperm);
+ // procpriority(p, pri, 0);
break;
case CMfixedpri:
- pri = atoi(cb->f[1]);
- if(pri > PriNormal && !iseve())
- error(Eperm);
- procpriority(p, pri, 1);
+ // pri = atoi(cb->f[1]);
+ // if(pri > PriNormal && !iseve())
+ // error(Eperm);
+ // procpriority(p, pri, 1);
break;
case CMprivate:
- p->privatemem = 1;
+ // p->privatemem = 1;
/*
* pages will now get marked private
* when faulted in for writing
* so force a tlb flush.
*/
- p->newtlb = 1;
- if(p == up)
- flushmmu();
+ // p->newtlb = 1;
+ // if(p == up)
+ // flushmmu();
break;
case CMprofile:
- s = p->seg[TSEG];
- if(s == nil || (s->type&SG_TYPE) != SG_TEXT) /* won't expand */
- error(Egreg);
- eqlock(s);
- npc = (s->size-s->start)>>LRESPROF;
- if(s->profile == nil){- s->profile = malloc(npc*sizeof(*s->profile));
- if(s->profile == nil){- qunlock(s);
- error(Enomem);
- }
- } else {- memset(s->profile, 0, npc*sizeof(*s->profile));
- }
- qunlock(s);
+ // s = p->seg[TSEG];
+ // if(s == nil || (s->type&SG_TYPE) != SG_TEXT) /* won't expand */
+ // error(Egreg);
+ // qlock(s);
+ // npc = (s->size-s->start)>>LRESPROF;
+ // if(s->profile == nil){+ // s->profile = malloc(npc*sizeof(*s->profile));
+ // if(s->profile == nil){+ // qunlock(s);
+ // error(Enomem);
+ // }
+ // } else {+ // memset(s->profile, 0, npc*sizeof(*s->profile));
+ // }
+ // qunlock(s);
break;
case CMstart:
- if(p->state != Stopped)
- error(Ebadctl);
- ready(p);
+ //if(p->state != Stopped)
+ // error(Ebadctl);
+ //ready(p);
break;
case CMstartstop:
- if(p->state != Stopped)
- error(Ebadctl);
- p->procctl = Proc_traceme;
- ready(p);
- procstopwait(p, Proc_traceme);
+ //if(p->state != Stopped)
+ // error(Ebadctl);
+ //p->procctl = Proc_traceme;
+ //ready(p);
+ //procstopwait(p, Proc_traceme);
break;
case CMstartsyscall:
- if(p->state != Stopped)
- error(Ebadctl);
- p->procctl = Proc_tracesyscall;
- ready(p);
- procstopwait(p, Proc_tracesyscall);
+ //if(p->state != Stopped)
+ // error(Ebadctl);
+ //p->procctl = Proc_tracesyscall;
+ //ready(p);
+ //procstopwait(p, Proc_tracesyscall);
break;
case CMstop:
procstopwait(p, Proc_stopme);
@@ -919,29 +1023,26 @@
case CMwaitstop:
procstopwait(p, 0);
break;
- case CMwired:
- procwired(p, atoi(cb->f[1]));
- break;
case CMtrace:
- switch(cb->nf){- case 1:
- p->trace ^= 1;
- break;
- case 2:
- p->trace = (atoi(cb->f[1]) != 0);
- break;
- default:
- error("args");- }
+ // switch(cb->nf){+ // case 1:
+ // p->trace ^= 1;
+ // break;
+ // case 2:
+ // p->trace = (atoi(cb->f[1]) != 0);
+ // break;
+ // default:
+ // error("args");+ // }
break;
case CMinterrupt:
- procinterrupt(p);
+ // procinterrupt(p);
break;
case CMnointerrupt:
- if(p->nnote == 0)
- p->notepending = 0;
- else
- error("notes pending");+ // if(p->nnote == 0)
+ // p->notepending = 0;
+ // else
+ // error("notes pending");break;
}
@@ -962,55 +1063,51 @@
Segment *s;
int i;
- eqlock(&p->seglock);
+ qlock(&p->seglock);
if(waserror()) {qunlock(&p->seglock);
nexterror();
}
- if(p->state <= New || p->pid != PID(c->qid))
+ if(p->pid != PID(c->qid))
error(Eprocdied);
- s = seg(p, offset, 1);
- if(s == nil)
- error(Ebadarg);
- if(waserror()){- qunlock(s);
- nexterror();
- }
- for(i = 0; i < NSEG; i++) {- if(p->seg[i] == s)
- break;
- }
- if(i == NSEG)
- error(Egreg); /* segment gone */
- if(!read && (s->type&SG_TYPE) == SG_TEXT) {- p->seg[i] = txt2data(s);
- qunlock(s);
- putseg(s);
- s = p->seg[i];
- } else {- qunlock(s);
- }
- poperror();
- incref(s); /* for us while we copy */
+ //s = seg(p, offset, 1);
+ //if(s == nil)
+ // error(Ebadarg);
+ //if(waserror()){+ // qunlock(s);
+ // nexterror();
+ //}
+ //for(i = 0; i < NSEG; i++) {+ // if(p->seg[i] == s)
+ // break;
+ //}
+ //if(i == NSEG)
+ // error(Egreg); /* segment gone */
+ //if(!read && (s->type&SG_TYPE) == SG_TEXT) {+ // p->seg[i] = txt2data(s);
+ // qunlock(s);
+ // putseg(s);
+ // s = p->seg[i];
+ //} else {+ // qunlock(s);
+ //}
+ //poperror();
+ //incref(s); /* for us while we copy */
qunlock(&p->seglock);
poperror();
- if(waserror()) {- putseg(s);
- nexterror();
- }
- offset -= s->base;
- putseg(s);
- poperror();
-
- if(!read)
- p->newtlb = 1;
-
+ //if(waserror()) {+ // putseg(s);
+ // nexterror();
+ //}
+ //offset -= s->start;
+ //putseg(s);
+ //poperror();
return n;
}
Dev procdevtab = {- 'P',
+ 'p',
"proc",
devreset,
@@ -1024,6 +1121,7 @@
procclose,
procread,
devbread,
+ procwrite,
devbwrite,
devremove,
procwstat,
--- a/kern/devtab.c
+++ b/kern/devtab.c
@@ -16,7 +16,7 @@
extern Dev lfddevtab;
extern Dev cmddevtab;
extern Dev envdevtab;
-//extern Dev procdevtab;
+extern Dev procdevtab;
Dev *devtab[] = {&rootdevtab,
@@ -31,7 +31,7 @@
&lfddevtab,
&cmddevtab,
&envdevtab,
-// &procdevtab,
+ &procdevtab,
0
};
--- a/kern/fns.h
+++ b/kern/fns.h
@@ -142,7 +142,7 @@
void oscmdfree(void*);
void oserrstr(void);
void oserror(void);
-void osexit(void);
+void osexit(char*);
Block* packblock(Block*);
Block* padblock(Block*, int);
void panic(char*, ...);
@@ -249,6 +249,7 @@
void osmsleep(int);
ulong ticks(void);
void osproc(Proc*);
+int osawait(Proc *, char *, int);
void osnewproc(Proc*);
void procsleep(void);
void procwakeup(Proc*);
--- a/kern/posix.c
+++ b/kern/posix.c
@@ -37,6 +37,8 @@
#include "mem.h"
#include <a.out.h>
+pthread_t thids[64];
+
typedef struct Oproc Oproc;
struct Oproc
{@@ -78,6 +80,24 @@
signal(SIGPIPE, SIG_IGN);
}
+int
+osawait(Proc *proc, char *str, int n)
+{+ void *msg;
+ int pid;
+ ulong time[3] = {1000, 1000, 1000};+
+ if(!proc->child)
+ return -1;
+ pid = proc->child->pid;
+ if(pthread_join(thids[pid], &msg) != 0)
+ return -1;
+
+ // TODO: Actual TUser, TSys, TReal
+ snprint(str, n, "%d %ux %lud %lud %lud %q", pid, time[0], time[1], time[2], msg);
+ return sizeof(str);
+}
+
void
osnewproc(Proc *p)
{@@ -148,14 +168,16 @@
oserrstr();
panic("osproc: %r");}
+
+ thids[p->pid] = pid;
sched_yield();
}
void
-osexit(void)
+osexit(char *ret)
{pthread_setspecific(prdakey, 0);
- pthread_exit(0);
+ pthread_exit(ret);
}
void
--- a/kern/procinit.c
+++ b/kern/procinit.c
@@ -42,6 +42,18 @@
return p;
}
+Proc*
+proctab(int i)
+{+ Proc *p;
+
+ for(p = up; p != nil; p = p->parent) {+ if(p->pid == i)
+ return p;
+ }
+ return nil;
+}
+
int
kproc(char *name, void (*fn)(void*), void *arg)
{@@ -53,6 +65,7 @@
p->slash = cclone(up->slash);
p->dot = cclone(up->dot);
p->rgrp = up->rgrp;
+ p->parent = up;
if(p->rgrp != nil)
incref(&p->rgrp->ref);
p->pgrp = up->pgrp;
@@ -75,7 +88,6 @@
{Proc *p = up;
- USED(msg);
USED(freemem);
if(p->pgrp != nil){@@ -95,5 +107,5 @@
cclose(p->slash);
free(p);
- osexit();
+ osexit(msg);
}
--- a/kern/seg.c
+++ b/kern/seg.c
@@ -43,11 +43,14 @@
freesegs(void)
{Segment **s, *ss;
-
+
for(s = up->seg; s < up->seg + NSEG; s++) {if(*s == nil)
continue;
ss = *s;
+ // Assure we don't have any weird state
+ if(!ss->dref || ss->dref->ref == 0 || !&ss->ref.ref == 0)
+ continue;
if(decref(ss->dref) == 0)
free(ss->dref);
if(decref(&ss->ref) == 0)
@@ -133,7 +136,7 @@
case SG_DATA: /* Copy on write plus demand load info */
if(segno == TSEG){n = data2txt(s);
- qunlock(s);
+ qunlock(&s->rw);
poperror();
return n;
}
@@ -145,12 +148,12 @@
if(n != nil && n != s)
memcpy(n->data, s->data, s->size);
- qunlock(s);
+ qunlock(&s->rw);
poperror();
return n;
sameseg:
incref(s);
- qunlock(s);
+ qunlock(&s->rw);
poperror();
return s;
}
--- a/kern/syscall.c
+++ b/kern/syscall.c
@@ -21,18 +21,6 @@
return p;
}
-static char*
-estrdup(char *s)
-{- char *d;
- int n;
-
- n = strlen(s)+1;
- d = emalloc(n);
- memmove(d, s, n);
- return d;
-}
-
static u32int
arg(int n)
{@@ -286,10 +274,16 @@
static void
_sysexits(void)
{- if(arg(0) == 0)
- exits(nil);
- else
- exits(vaddrnol(arg(0), 0));
+ if(arg(0) == 0) {+ if(debug)
+ print("sysexits\n");+ pexit("", 0);+ } else {+ if(debug)
+ print("sysexits: %s\n", vaddrnol(arg(0), 0));+ pexit(vaddrnol(arg(0), 0), 0);
+ }
+
}
static void
@@ -412,7 +406,9 @@
segunlock(seg2);
}
segunlock(seg1);
+
rc = loadtext(namet, argc, argvv);
+
for(i = 0; i < argc; i++)
free(argvv[i]);
free(argvv);
--- a/kern/sysproc.c
+++ b/kern/sysproc.c
@@ -290,6 +290,15 @@
up->R[15] = ureg[17];
}
+void
+inittos(Proc *p)
+{+ ulong tos;
+
+ tos = (USTKTOP & ~7) - sizeof(Tos) * 2;
+ ((Tos *) vaddrnol(tos, sizeof(Tos)))->pid = p->pid;
+}
+
static void
initstack(int argc, char **argv)
{@@ -322,18 +331,9 @@
ap += len;
}
*(ulong *) vaddrnol(sp, 4) = 0;
- inittos();
+ inittos(up);
}
-void
-inittos(void)
-{- ulong tos;
-
- tos = (USTKTOP & ~7) - sizeof(Tos) * 2;
- ((Tos *) vaddrnol(tos, sizeof(Tos)))->pid = up->pid;
-}
-
static int
loadscript(int fd, char *file, int argc, char **argv)
{@@ -394,7 +394,7 @@
Exec hdr;
char buf[2];
int fd;
-
+
fd = open(file, OREAD);
if(fd < 0) return -1;
if(pread(fd, buf, 2, 0) == 2 && buf[0] == '#' && buf[1] == '!')
@@ -589,8 +589,7 @@
pgrpcpy(p->pgrp, up->pgrp);
/* inherit notallowed */
memmove(p->pgrp->notallowed, up->pgrp->notallowed, sizeof p->pgrp->notallowed);
- }
- else {+ } else {p->pgrp = up->pgrp;
incref(p->pgrp);
}
@@ -610,23 +609,25 @@
p->egrp->ref.ref = 1;
if(flag & RFENVG)
envcpy(p->egrp, up->egrp);
- }
- else {+ } else {p->egrp = up->egrp;
incref(p->egrp);
}
p->fn = procrun;
+ p->parent = up;
p->arg = 0;
poperror();
if((flag&RFNOWAIT) == 0){// TODO: Actually use parent + ppid
- p->parent = up;
lock(&up->exl);
up->nchild++;
unlock(&up->exl);
}
+ inittos(p);
osproc(p);
+ up->child = p;
+
return p->pid;
}
--- a/kern/wait.c
+++ b/kern/wait.c
@@ -35,19 +35,3 @@
return _wait(await(buf, sizeof buf-1), buf);
}
-
-Waitmsg*
-waitnohang(void)
-{- char buf[256];
-
- return _wait(awaitnohang(buf, sizeof buf-1), buf);
-}
-
-Waitmsg*
-waitfor(int pid)
-{- char buf[256];
-
- return _wait(awaitfor(pid, buf, sizeof buf-1), buf);
-}
--- a/kern/win32.c
+++ b/kern/win32.c
@@ -106,7 +106,7 @@
}
void
-osexit(void)
+osexit(char *str)
{ExitThread(0);
}
--- a/main.c
+++ b/main.c
@@ -120,8 +120,8 @@
panic("bind #I: %r"); if(bind("#U", "/root", MREPL|MCREATE) < 0) panic("bind #U: %r");- //if(bind("#P", "/proc", MBEFORE) < 0)- // panic("bind #P: %r");+ if(bind("#p", "/proc", MBEFORE) < 0)+ panic("bind #p: %r"); if(bind(smprint("/root/%s/arm", ninepath), "/arm", MREPL|MCREATE) < 0) panic("bind arm: %r"); if(bind(smprint("/root/%s/rc", ninepath), "/rc", MREPL|MCREATE) < 0)--
⑨