ref: 877bce095a192ead0e9b6e0d5ce3071482cf0f6e
parent: f11139d4c918802a87730bc14d094670ee4ce572
author: cinap_lenrek <[email protected]>
date: Sun Sep 8 10:13:06 EDT 2024
implement procinterrupt() To handle flushes properly, we have to implement procinterrupt() to pull a process out of a sleep()/tsleep() or rendezvous(). Drawterm never implemented postnote, theres no note system. And there is also no global process table, so we make kproc() return just the Proc* pointer and add getkproc() and kprocint() "system calls" to work on Proc* pointer directly instead of translating from pids.
--- a/aan.c
+++ b/aan.c
@@ -32,10 +32,6 @@
int pipefd;
int timeout;
- int reader;
- int writer;
- int syncer;
-
ulong inmsg;
ulong outmsg;
@@ -211,8 +207,8 @@
c->timeout = 60;
reconnect(c);
c->timeout = timeout;
- c->writer = kproc("aanwriter", aanwriter, c);
- c->reader = kproc("aanreader", aanreader, c);
- c->syncer = kproc("aansyncer", aansyncer, c);
+ kproc("aanwriter", aanwriter, c);
+ kproc("aanreader", aanreader, c);
+ kproc("aansyncer", aansyncer, c);
return pfd[0];
}
--- a/exportfs/exportfs.c
+++ b/exportfs/exportfs.c
@@ -224,7 +224,7 @@
}
wb = &Workq[ap];
- wb->pid = 0;
+ wb->kp = nil;
wb->canint = 0;
wb->flushtag = NOTAG;
wb->busy = 1;
@@ -484,6 +484,7 @@
{
char buf[ERRMAX];
va_list arg;
+ Proc *m;
if (s != nil) {
va_start(arg, s);
@@ -492,8 +493,8 @@
}
/* Clear away the slave children */
-// for(m = Proclist; m; m = m->next)
-// postnote(PNPROC, m->pid, "kill");
+ for(m = Proclist; m; m = m->next)
+ kprocint(m->kp);
if (s != nil) {
DEBUG(DFD, "%s\n", buf);
--- a/exportfs/exportfs.h
+++ b/exportfs/exportfs.h
@@ -18,7 +18,7 @@
struct Fsrpc
{
int busy; /* Work buffer has pending rpc to service */
- int pid; /* Pid of slave process executing the rpc */
+ void* kp; /* slave process executing the rpc */
int canint; /* Interrupt gate */
int flushtag; /* Tag on which to reply to flush */
Fcall work; /* Plan 9 incoming Fcall */
@@ -49,7 +49,7 @@
struct Proc
{
- int pid;
+ void *kp;
int busy;
Proc *next;
};
--- a/exportfs/exportsrv.c
+++ b/exportfs/exportsrv.c
@@ -63,12 +63,12 @@
for(w = Workq; w < e; w++) {
if(w->work.tag == t->work.oldtag) {
- DEBUG(DFD, "\tQ busy %d pid %d can %d\n", w->busy, w->pid, w->canint);
- if(w->busy && w->pid) {
+ DEBUG(DFD, "\tQ busy %d kp %d can %d\n", w->busy, w->kp, w->canint);
+ if(w->busy && w->kp) {
w->flushtag = t->work.tag;
DEBUG(DFD, "\tset flushtag %d\n", t->work.tag);
- // if(w->canint)
- // postnote(PNPROC, w->pid, "flush");
+ if(w->canint)
+ kprocint(w->kp);
t->busy = 0;
return;
}
@@ -421,28 +421,26 @@
slave(Fsrpc *f)
{
Proc *p;
- int pid;
+ void *kp;
static int nproc;
for(;;) {
for(p = Proclist; p; p = p->next) {
if(p->busy == 0) {
- f->pid = p->pid;
+ f->kp = p->kp;
p->busy = 1;
- pid = (uintptr)rendezvous((void*)(uintptr)p->pid, f);
- if(pid != p->pid)
+ kp = rendezvous(p->kp, f);
+ if(kp != p->kp)
fatal("rendezvous sync fail");
return;
- }
+ }
}
if(++nproc > MAXPROC)
fatal("too many procs");
- pid = kproc("slave", blockingslave, nil);
- DEBUG(DFD, "slave pid %d\n", pid);
- if(pid == -1)
- fatal("kproc");
+ kp = kproc("slave", blockingslave, nil);
+ DEBUG(DFD, "slave kp %p\n", kp);
p = malloc(sizeof(Proc));
if(p == 0)
@@ -449,13 +447,13 @@
fatal("out of memory");
p->busy = 0;
- p->pid = pid;
+ p->kp = kp;
p->next = Proclist;
Proclist = p;
-DEBUG(DFD, "parent %d rendez\n", pid);
- rendezvous((void*)(uintptr)pid, p);
-DEBUG(DFD, "parent %d went\n", pid);
+DEBUG(DFD, "parent %p rendez\n", kp);
+ rendezvous(kp, p);
+DEBUG(DFD, "parent %p went\n", kp);
}
}
@@ -465,24 +463,24 @@
Fsrpc *p;
Fcall rhdr;
Proc *m;
- int pid;
+ void *kp;
USED(x);
+ kp = getkproc();
+
notify(flushaction);
- pid = getpid();
-
-DEBUG(DFD, "blockingslave %d rendez\n", pid);
- m = (Proc*)rendezvous((void*)(uintptr)pid, 0);
-DEBUG(DFD, "blockingslave %d rendez got %p\n", pid, m);
+DEBUG(DFD, "blockingslave %p rendez\n", kp);
+ m = rendezvous(kp, 0);
+DEBUG(DFD, "blockingslave %p rendez got %p\n", kp, m);
for(;;) {
- p = rendezvous((void*)(uintptr)pid, (void*)(uintptr)pid);
+ p = rendezvous(kp, kp);
if((uintptr)p == ~(uintptr)0) /* Interrupted */
continue;
- DEBUG(DFD, "\tslave: %d %F b %d p %d\n", pid, &p->work, p->busy, p->pid);
+ DEBUG(DFD, "\tslave: %p %F b %d p %p\n", kp, &p->work, p->busy, p->kp);
if(p->flushtag != NOTAG)
goto flushme;
--- a/include/user.h
+++ b/include/user.h
@@ -19,6 +19,8 @@
#define pipe syspipe
#define rendezvous sysrendezvous
#define getpid sysgetpid
+#define getkproc sysgetkproc
+#define kprocint syskprocint
#define time systime
#define nsec sysnsec
#define pread syspread
@@ -77,7 +79,9 @@
extern long pread(int, void*, long, vlong);
extern long pwrite(int, void*, long, vlong);
extern void* rendezvous(void*, void*);
-extern int kproc(char*, void(*)(void*), void*);
+extern void* kproc(char*, void(*)(void*), void*);
+extern void kprocint(void*);
+extern void* getkproc(void);
extern int getpid(void);
extern void panic(char*, ...);
extern void sleep(int);
--- a/kern/fns.h
+++ b/kern/fns.h
@@ -80,7 +80,7 @@
#define islo() (0)
int kbdputc(Queue*, int);
void kbdkey(Rune, int);
-int kproc(char*, void(*)(void*), void*);
+void* kproc(char*, void(*)(void*), void*);
void ksetenv(char*, char*, int);
void kstrcpy(char*, char*, int);
void kstrdup(char**, char*);
@@ -137,6 +137,7 @@
Pgrp* pgrptab(int);
#define poperror() up->nerrlab--
int postnote(Proc*, int, char*, int);
+void procinterrupt(Proc*);
int pprint(char*, ...);
int procfdprint(Chan*, int, int, char*, int);
void procinit0(void);
--- a/kern/procinit.c
+++ b/kern/procinit.c
@@ -38,7 +38,7 @@
return p;
}
-int
+void*
kproc(char *name, void (*fn)(void*), void *arg)
{
Proc *p;
@@ -60,7 +60,7 @@
strecpy(p->text, p->text+sizeof p->text, name);
osproc(p);
- return p->pid;
+ return (void*)p;
}
void
--- a/kern/sleep.c
+++ b/kern/sleep.c
@@ -88,3 +88,87 @@
return p;
}
+/*
+ * if waking a sleeping process, this routine must hold both
+ * p->rlock and r->lock. However, it can't know them in
+ * the same order as wakeup causing a possible lock ordering
+ * deadlock. We break the deadlock by giving up the p->rlock
+ * lock if we can't get the r->lock and retrying.
+ */
+void
+procinterrupt(Proc *p)
+{
+ int s;
+
+ p->notepending = 1;
+
+ /* this loop is to avoid lock ordering problems. */
+ for(;;){
+ Rendez *r;
+
+ s = splhi();
+ lock(&p->rlock);
+ r = p->r;
+
+ /* waiting for a wakeup? */
+ if(r == nil)
+ break; /* no */
+
+ /* try for the second lock */
+ if(canlock(&r->lk)){
+ if(p->state != Wakeme || r->p != p)
+ panic("procinterrupt: state %d %d %d",
+ r->p != p, p->r != r, p->state);
+ p->r = nil;
+ r->p = nil;
+ unlock(&p->rlock);
+ unlock(&r->lk);
+ /* hands off r */
+ procwakeup(p);
+ splx(s);
+ return;
+ }
+
+ /* give other process time to get out of critical section and try again */
+ unlock(&p->rlock);
+ splx(s);
+
+ osyield();
+ }
+ unlock(&p->rlock);
+ splx(s);
+
+ switch(p->state){
+ case Rendezvous:
+ /* Try and pull out of a rendezvous */
+ lock(&p->rgrp->ref.lk);
+ if(p->state == Rendezvous) {
+ Proc *d, **l;
+
+ l = &REND(p->rgrp, (uintptr)p->rendtag);
+ for(d = *l; d != nil; d = d->rendhash) {
+ if(d == p) {
+ *l = p->rendhash;
+ p->rendval = (void*)~(uintptr)0;
+ unlock(&p->rgrp->ref.lk);
+ /* hands off p->rgrp */
+ procwakeup(p);
+ return;
+ }
+ l = &d->rendhash;
+ }
+ }
+ unlock(&p->rgrp->ref.lk);
+ break;
+ }
+}
+
+int
+postnote(Proc *p, int x, char *msg, int flag)
+{
+ USED(x);
+ USED(msg);
+ USED(flag);
+ procinterrupt(p);
+ return 0;
+}
--- a/kern/stub.c
+++ b/kern/stub.c
@@ -60,16 +60,6 @@
USED(tag);
}
-int
-postnote(Proc *p, int x, char *msg, int flag)
-{
- USED(p);
- USED(x);
- USED(msg);
- USED(flag);
- return 0;
-}
-
void
exhausted(char *s)
{
--- a/kern/sysfile.c
+++ b/kern/sysfile.c
@@ -1251,3 +1251,16 @@
{
return up->pid;
}
+
+void*
+sysgetkproc(void)
+{
+ return (void*)up;
+}
+
+void
+syskprocint(void *p)
+{
+ if(p != nil)
+ procinterrupt((Proc*)p);
+}
--- a/kern/term.c
+++ b/kern/term.c
@@ -221,7 +221,6 @@
{
static char rb[UTFmax+1];
static int nrb;
- int locked;
char *e;
e = s + n;