M gnot/clock.c => gnot/clock.c +5 -4
@@ 106,14 106,15 @@ clock(Ureg *ur)
p->time[p->insyscall]++;
}
if(canlock(&m->alarmlock)){
- if(m->alarm){
- a = m->alarm;
- a->dt--;
- for(n = 0; a && a->dt<=0 && n<NA; n++){
+ a = m->alarm;
+ if(a){
+ for(n=0; a && a->dt<=0 && n<NA; n++){
alist[n] = a;
delete(&m->alarm, 0, a);
a = m->alarm;
}
+ if(a)
+ a->dt--;
unlock(&m->alarmlock);
/* execute alarm functions outside the lock */
M gnot/dat.h => gnot/dat.h +5 -1
@@ 103,6 103,7 @@ struct Chan
union {
Stream *stream; /* for stream channels */
void *aux;
+ ulong pgrpid; /* for #p/notepg */
};
Chan *mchan; /* channel to mounted server */
ulong mqid; /* qid of root of mount point */
@@ 278,10 279,12 @@ struct Pgrp
{
Ref; /* also used as a lock when mounting */
Pgrp *next;
+ int index; /* index in pgrp table */
ulong pgrpid;
char user[NAMELEN];
int nmtab; /* highest active mount table entry, +1 */
int nenv; /* highest active env table entry, +1 */
+ Lock debug; /* single access via devproc.c */
Mtab *mtab;
Envp *etab;
};
@@ 499,7 502,8 @@ struct Service
Service *next;
QLock alock;
int die;
- Chan *c;
+ Chan *inc;
+ Chan *outc;
char name[NAMELEN];
};
M gnot/devproc.c => gnot/devproc.c +33 -1
@@ 12,6 12,7 @@ enum{
Qctl,
Qmem,
Qnote,
+ Qnotepg,
Qproc,
Qstatus,
Qtext,
@@ 21,6 22,7 @@ Dirtab procdir[]={
"ctl", Qctl, 0, 0600,
"mem", Qmem, 0, 0600,
"note", Qnote, 0, 0600,
+ "notepg", Qnotepg, 0, 0200,
"proc", Qproc, sizeof(Proc), 0600,
"status", Qstatus, NAMELEN+12+6*12, 0600,
"text", Qtext, 0, 0600,
@@ 108,6 110,7 @@ Chan *
procopen(Chan *c, int omode)
{
Proc *p;
+ Pgrp *pg;
Orig *o;
Chan *tc;
@@ 117,6 120,7 @@ procopen(Chan *c, int omode)
goto done;
}
p = proctab(SLOT(c->qid));
+ pg = p->pgrp;
if((p->pid&PIDMASK) != PID(c->qid))
Died:
error(0, Eprocdied);
@@ 146,11 150,18 @@ procopen(Chan *c, int omode)
case Qctl:
case Qnote:
break;
+
+ case Qnotepg:
+ if(omode != OWRITE)
+ error(0, Eperm);
+ c->pgrpid = (pg->pgrpid<<PIDSHIFT)|((pg->index+1)<<QSHIFT);
+ break;
+
case Qdir:
case Qmem:
case Qproc:
case Qstatus:
- if(omode!=OREAD)
+ if(omode != OREAD)
error(0, Eperm);
break;
default:
@@ 347,12 358,33 @@ long
procwrite(Chan *c, void *va, long n)
{
Proc *p;
+ Pgrp *pg;
User *up;
KMap *k;
char buf[ERRLEN];
if(c->qid & CHDIR)
error(0, Eisdir);
+
+ /*
+ * Special case: don't worry about process, just use remembered group
+ */
+ if(QID(c->qid) == Qnotepg){
+ pg = pgrptab(SLOT(c->pgrpid));
+ lock(&pg->debug);
+ if(waserror()){
+ unlock(&pg->debug);
+ nexterror();
+ }
+ if((pg->pgrpid&PIDMASK) != PID(c->pgrpid)){
+ unlock(&pg->debug);
+ goto Died;
+ }
+ pgrpnote(pg, va, n, NUser);
+ unlock(&pg->debug);
+ return n;
+ }
+
p = proctab(SLOT(c->qid));
lock(&p->debug);
if(waserror()){
M gnot/fns.h => gnot/fns.h +14 -9
@@ 19,6 19,7 @@ long clrfpintr(void);
int compactpte(Orig*, ulong);
void confinit(void);
Env *copyenv(Env*, int);
+Chan *createdir(Chan*);
int decref(Ref*);
void delay(int);
void delete(List**, List*, List*);
@@ 29,7 30,7 @@ void devdir(Chan*, long, char*, long, long, Dir*);
long devdirread(Chan*, char*, long, Dirtab*, int, Devgen*);
Devgen devgen;
int devno(int, int);
-Chan* devopen(Chan*, int, Dirtab*, int, Devgen*);
+Chan *devopen(Chan*, int, Dirtab*, int, Devgen*);
void devstat(Chan*, char*, Dirtab*, int, Devgen*);
int devwalk(Chan*, char*, Dirtab*, int, Devgen*);
void duartbaud(int);
@@ 47,7 48,7 @@ void error(Chan*, int);
void exit(void);
void fault(Ureg*, FFrame*);
void fdclose(int);
-Chan* fdtochan(int, int);
+Chan *fdtochan(int, int);
void filsys(Chan*, char*, long);
void firmware(void);
void flowctl(Queue*);
@@ 81,7 82,7 @@ void kbdclock(void);
void kmapinit(void);
KMap *kmap(Page*);
int kprint(char*, ...);
-Proc *kproc(char*, void(*)(void*), void*);
+void *kproc(char*, void(*)(void*), void*);
void kunmap(KMap*);
void lock(Lock*);
void lockinit(void);
@@ 107,19 108,21 @@ char *nextelem(char*, char*);
void notify(Ureg*);
void nullput(Queue*, Block*);
int openmode(ulong);
-Block* padb(Block*, int);
+Block *padb(Block*, int);
void pageinit(void);
void panic(char*, ...);
void pexit(char*, int);
void pgrpcpy(Pgrp*, Pgrp*);
void pgrpinit(void);
+void pgrpnote(Pgrp*, char*, long, int);
+Pgrp *pgrptab(int);
int postnote(Proc*, int, char*, int);
int pprint(char*, ...);
void printinit(void);
void printslave(void);
void procinit0(void);
Proc *proctab(int);
-Queue* pushq(Stream*, Qinfo*);
+Queue *pushq(Stream*, Qinfo*);
void putbq(Blist*, Block*);
void putkmmu(ulong, ulong);
void putmmu(ulong, ulong);
@@ 146,9 149,9 @@ long seconds(void);
Seg *seg(Proc*, ulong);
int segaddr(Seg*, ulong, ulong);
void serviceinit(void);
-void service(char*, Chan*, void (*)(Chan*, char*, long));
+void service(char*, Chan*, Chan*, void (*)(Chan*, char*, long));
int setlabel(Label*);
-char* skipslash(char*);
+char *skipslash(char*);
void sleep(Rendez*, int(*)(void*), void*);
int splhi(void);
int spllo(void);
@@ 162,7 165,7 @@ int streamexit(Stream*, int);
void streaminit(void);
long streamread(Chan*, void*, long);
long streamwrite(Chan*, void*, long, int);
-Stream* streamnew(ushort, ushort, ushort, Qinfo*, int);
+Stream *streamnew(ushort, ushort, ushort, Qinfo*, int);
void streamopen(Chan*, Qinfo*);
int streamparse(char*, Block*);
void streamstat(Chan*, char*, char*);
@@ 172,13 175,15 @@ int tas(char*);
void touser(void);
void tsleep(Rendez*, int (*)(void*), void*, int);
void twakeme(Alarm*);
+long unionread(Chan*, void*, long);
void unlock(Lock*);
void usepage(Page*, int);
void userinit(void);
void validaddr(ulong, ulong, int);
-void* vmemchr(void*, int, int);
+void *vmemchr(void*, int, int);
void wakeme(Alarm*);
void wakeup(Rendez*);
+Chan *walk(Chan*, char*, int);
#define waserror() (u->nerrlab++, setlabel(&u->errlab[u->nerrlab-1]))
#define poperror() u->nerrlab--
M gnot/pgrp.c => gnot/pgrp.c +42 -1
@@ 7,6 7,7 @@
struct{
Lock;
+ Pgrp *arena;
Pgrp *free;
ulong pgrpid;
}pgrpalloc;
@@ 24,10 25,12 @@ pgrpinit(void)
Pgrp *p;
Mount *m;
- pgrpalloc.free = ialloc(conf.npgrp*sizeof(Pgrp), 0);
+ pgrpalloc.arena = ialloc(conf.npgrp*sizeof(Pgrp), 0);
+ pgrpalloc.free = pgrpalloc.arena;
p = pgrpalloc.free;
for(i=0; i<conf.npgrp; i++,p++){
+ p->index = i;
p->next = p+1;
p->mtab = ialloc(conf.nmtab*sizeof(Mtab), 0);
p->etab = ialloc(conf.npgenv*sizeof(Envp*), 0);
@@ 43,6 46,43 @@ pgrpinit(void)
}
Pgrp*
+pgrptab(int i)
+{
+ return &pgrpalloc.arena[i];
+}
+
+void
+pgrpnote(Pgrp *pg, char *a, long n, int flag)
+{
+ int i;
+ Proc *p;
+ char buf[ERRLEN];
+
+ if(n >= ERRLEN-1)
+ error(0, Etoobig);
+ if(n>=4 && strncmp(a, "sys:", 4)==0)
+ error(0, Ebadarg);
+ memcpy(buf, a, n);
+ buf[n] = 0;
+ p = proctab(0);
+ for(i=0; i<conf.nproc; i++, p++){
+ if(p->pgrp == pg){
+ lock(&p->debug);
+ if(p->pid==0 || p->pgrp!=pg){
+ unlock(&p->debug);
+ continue;
+ }
+ if(waserror()){
+ unlock(&p->debug);
+ continue;
+ }
+ postnote(p, 0, buf, flag);
+ unlock(&p->debug);
+ }
+ }
+}
+
+Pgrp*
newpgrp(void)
{
Pgrp *p;
@@ 76,6 116,7 @@ closepgrp(Pgrp *p)
Envp *ep;
if(decref(p) == 0){
+ p->pgrpid = -1;
m = p->mtab;
for(i=0; i<p->nmtab; i++,m++)
if(m->c){
M gnot/proc.c => gnot/proc.c +21 -20
@@ 58,13 58,13 @@ schedinit(void) /* never returns */
/*
* At init time: wait for a process on the run queue.
*/
- for (;;) {
+ for(;;){
spllo();
while (runq.head == 0)
/* idle loop */;
splhi();
lock(&runq);
- if (runq.head != 0)
+ if(runq.head != 0)
break;
unlock(&runq);
}
@@ 84,7 84,7 @@ schedinit(void) /* never returns */
* to have a process on it.
*/
p = runq.head;
- if ((runq.head = p->rnext) == 0)
+ if((runq.head = p->rnext) == 0)
runq.tail = 0;
unlock(&runq);
@@ 108,7 108,7 @@ restore(void)
u->p->mach = m;
m->proc = u->p;
u->p->state = Running;
- if (p->state == Moribund) {
+ if(p->state == Moribund){
p->pid = 0;
unlock(&p->debug); /* set in pexit */
p->upage->ref--;
@@ 127,16 127,16 @@ void
save(Balu *balu)
{
fpsave(&u->fpsave);
- if (u->fpsave.type) {
+ if(u->fpsave.type){
if(u->fpsave.size > sizeof u->fpsave.junk)
panic("fpsize %d max %d\n", u->fpsave.size, sizeof u->fpsave.junk);
fpregsave(u->fpsave.reg);
u->p->fpstate = FPactive;
m->fpstate = FPdirty;
}
- if (BALU->cr0 != 0xFFFFFFFF) /* balu busy */
+ if(BALU->cr0 != 0xFFFFFFFF) /* balu busy */
memcpy(balu, BALU, sizeof *balu);
- else {
+ else{
balu->cr0 = 0xFFFFFFFF;
BALU->cr0 = 0xFFFFFFFF;
}
@@ 166,7 166,7 @@ sched(void)
/*
* Look for a new process to be run.
*/
- for (;;) {
+ for (;;){
spllo();
/*
@@ 174,9 174,9 @@ sched(void)
* to do, start saving some of the process state.
*/
while (runq.head == 0)
- if (p->state == Running)
+ if(p->state == Running)
return;
- else if (!saved) {
+ else if(!saved){
save(&balu);
saved = 1;
}
@@ 188,7 188,7 @@ sched(void)
*/
splhi();
lock(&runq);
- if (runq.head != 0)
+ if(runq.head != 0)
break;
unlock(&runq);
}
@@ 199,7 199,7 @@ sched(void)
* save our state before we jump to schedinit. If this process was running, put
* it on the run queue.
*/
- if (p->state == Running) {
+ if(p->state == Running){
p->state = Ready;
p->rnext = 0;
runq.tail->rnext = p;
@@ 211,9 211,9 @@ sched(void)
* pc and sp. We have to jump to schedinit() because we are going to remap the
* stack.
*/
- if (!saved)
+ if(!saved)
save(&balu);
- if (setlabel(&p->sched) == 0)
+ if(setlabel(&p->sched) == 0)
gotolabel(&m->sched);
/*
@@ 225,18 225,18 @@ sched(void)
/*
* Jumped to by schedinit. Restore the process state.
*/
- if (p->fpstate != m->fpstate)
- if (p->fpstate == FPinit) {
+ if(p->fpstate != m->fpstate)
+ if(p->fpstate == FPinit){
initfp = 0;
fprestore((FPsave *) &initfp);
m->fpstate = FPinit;
}
- else {
+ else{
fpregrestore(u->fpsave.reg);
fprestore(&u->fpsave);
m->fpstate = FPdirty;
}
- if (balu.cr0 != 0xFFFFFFFF) /* balu busy */
+ if(balu.cr0 != 0xFFFFFFFF) /* balu busy */
memcpy(BALU, &balu, sizeof balu);
/*
@@ 250,11 250,12 @@ ready(Proc *p)
{
int s;
- if (p->spin) {
+ s = splhi();
+ if(p->spin){
p->state = Running;
+ splx(s);
return;
}
- s = splhi();
lock(&runq);
p->rnext = 0;
if(runq.tail)
M gnot/sysfile.c => gnot/sysfile.c +6 -5
@@ 512,12 512,13 @@ sysfwstat(ulong *arg)
long
sysfilsys(ulong *arg)
{
- Chan *c;
+ Chan *cin, *cout;
- c = fdtochan(arg[0], -1);
- validaddr(arg[1], 1, 0);
- if((c->qid&CHDIR) || (c->mode&ORDWR)!=ORDWR)
+ cin = fdtochan(arg[0], OREAD);
+ cout = fdtochan(arg[1], OWRITE);
+ validaddr(arg[2], 1, 0);
+ if((cin->qid&CHDIR) || (cout->qid&CHDIR))
error(0, Ebadarg);
- service((char *)arg[1], c, filsys);
+ service((char *)arg[2], cin, cout, filsys);
return 0;
}
M power/clock.c => power/clock.c +7 -6
@@ 181,18 181,19 @@ clock(ulong n, ulong pc)
exit();
}
if(canlock(&m->alarmlock)){
- if(m->alarm){
- a = m->alarm;
- a->dt--;
- for(na = 0; a && a->dt<=0 && na<NA; na++){
- alist[na] = a;
+ a = m->alarm;
+ if(a){
+ for(n=0; a && a->dt<=0 && n<NA; n++){
+ alist[n] = a;
delete(&m->alarm, 0, a);
a = m->alarm;
}
+ if(a)
+ a->dt--;
unlock(&m->alarmlock);
/* execute alarm functions outside the lock */
- for(i = 0; i < na; i++){
+ for(i = 0; i < n; i++){
f = alist[i]->f; /* avoid race with cancel */
if(f)
(*f)(alist[i]);
M power/devhotrod.c => power/devhotrod.c +64 -5
@@ 10,6 10,7 @@
typedef struct Hotrod Hotrod;
typedef struct Device Device;
+typedef struct Printbuf Printbuf;
enum {
Vmevec= 0xd2, /* vme vector for interrupts */
@@ 18,6 19,16 @@ enum {
};
/*
+ * circular 2 pointer queue for hotrod prnt's
+ */
+struct Printbuf {
+ char *rptr;
+ char *wptr;
+ char *lim;
+ char buf[4*1024];
+};
+
+/*
* the hotrod fiber interface responds to 1MB
* of either user or supervisor accesses at:
* 0x30000000 to 0x300FFFFF in A32 space
@@ 31,14 42,18 @@ struct Device {
struct Hotrod {
QLock;
- Device *addr;
- int vec;
- char name[NAMELEN];
+ Device *addr; /* address of the device */
+ int vec; /* vme interrupt vector */
+ char name[NAMELEN]; /* hot rod name */
+ Printbuf pbuf; /* circular queue for hotrod print's */
+ int kprocstarted;
+ Rendez r;
};
Hotrod hotrod[Nhotrod];
-static void hotrodintr(int);
+void hotrodintr(int);
+void hotrodkproc(void *a);
int
hotrodgen(Chan *c, Dirtab *tab, int ntab, int i, Dir *dp)
@@ 79,6 94,7 @@ hotrodinit(void)
Chan*
hotrodattach(char *spec)
{
+ Hotrod *hp;
int i;
Chan *c;
@@ 86,6 102,10 @@ hotrodattach(char *spec)
if(i >= Nhotrod)
error(0, Ebadarg);
+ hp = &hotrod[i];
+ if(hp->kprocstarted == 0)
+ kproc(hp->name, hotrodkproc, hp);
+
c = devattach('H', spec);
c->dev = i;
c->qid = CHDIR;
@@ 113,6 133,17 @@ hotrodstat(Chan *c, char *dp)
Chan*
hotrodopen(Chan *c, int omode)
{
+ Device *dp;
+ Hotrod *hp;
+
+ /*
+ * Remind hotrod where the print buffer is. The address we store
+ * is the address of the printbuf in VME A32 space.
+ */
+ hp = &hotrod[c->dev];
+ dp = hp->addr;
+ dp->mem[256*1024/sizeof(ulong)] = (((ulong)&hp->pbuf) - KZERO) | (SLAVE<<28);
+
if(c->qid == CHDIR){
if(omode != OREAD)
error(0, Eperm);
@@ 238,7 269,7 @@ hotroderrstr(Error *e, char *buf)
rooterrstr(e, buf);
}
-static void
+void
hotrodintr(int vec)
{
Hotrod *hp;
@@ 250,3 281,31 @@ hotrodintr(int vec)
return;
}
}
+
+/*
+ * print hotrod processor messages on the console
+ */
+void
+hotrodkproc(void *a)
+{
+ Hotrod *hp = a;
+ char *p;
+
+ hp->kprocstarted = 1;
+ hp->pbuf.rptr = hp->pbuf.wptr = hp->pbuf.buf;
+ hp->pbuf.lim = &hp->pbuf.buf[sizeof(hp->pbuf.buf)];
+
+ for(;;){
+ p = hp->pbuf.wptr;
+ if(p != hp->pbuf.rptr){
+ if(p > hp->pbuf.rptr){
+ putstrn(hp->pbuf.rptr, p - hp->pbuf.rptr);
+ } else {
+ putstrn(hp->pbuf.rptr, hp->pbuf.lim - hp->pbuf.rptr);
+ putstrn(hp->pbuf.buf, hp->pbuf.wptr - hp->pbuf.buf);
+ }
+ hp->pbuf.rptr = p;
+ }
+ tsleep(&(hp->r), return0, 0, 1000);
+ }
+}