code: drawterm

Download patch

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;