Commit Diff


commit - ac0e2db600593d5b30550453b78874bfa0611751
commit + 175b8a534ae5729ac10ea793410a40bfa4a30608
blob - 713b9558d527438137d385224a3582f645889f41
blob + 663d65b6bee3f48695cfb0611cf91970825703d6
--- src/lib9/9proc.h
+++ src/lib9/9proc.h
@@ -2,15 +2,12 @@ enum
 {
 	NPRIV = 16,
 	RENDHASH = 33,
-	PIDHASH = 33,
 };
 
 typedef struct Uproc Uproc;
 struct Uproc
 {
-	Uproc *next;
 	int pid;
-	int pipe[2];
 	int state;
 	void *priv[NPRIV];
 	ulong rendval;
@@ -19,5 +16,5 @@ struct Uproc
 	p9jmp_buf notejb;
 };
 
-extern Uproc *_p9uproc(void);
+extern Uproc *_p9uproc(int);
 extern void _p9uprocdie(void);
blob - 6e4010cda8392e47c004f156a8cb2801187e391d
blob + 374fb089dc8ebb5eeb570392f8e49bb179d07cf5
--- src/lib9/_p9proc.c
+++ src/lib9/_p9proc.c
@@ -1,73 +1,95 @@
+/*
+ * This needs to be callable from a signal handler, so it has been
+ * written to avoid locks.  The only lock is the one used to acquire
+ * an entry in the table, and we make sure that acquiring is done
+ * when not in a handler.  Lookup and delete do not need locks.
+ * It's a scan-forward hash table.  To avoid breaking chains, 
+ * T ((void*)-1) is used as a non-breaking nil.
+ */
+
 #include <u.h>
 #include <libc.h>
 #include "9proc.h"
 
+enum { PIDHASH = 1021 };
+
+#define T ((void*)-1)
+static Uproc *alluproc[PIDHASH];
+static int allupid[PIDHASH];
 static Lock uproclock;
-static Uproc *phash[PIDHASH];
 
 Uproc*
-_p9uproc(void)
+_p9uproc(int inhandler)
 {
-	/* for now, assume getpid is fast or cached */
-	int pid;
+	int i, h, pid;
 	Uproc *up;
 
+	/* for now, assume getpid is fast or cached */
 	pid = getpid();
-again:
-if(0)print("find %d\n", pid);
-	lock(&uproclock);
-	for(up=phash[pid%PIDHASH]; up; up=up->next){
-		if(up->pid == pid){
-if(0)print("found %d\n", pid);
-			unlock(&uproclock);
+
+	/*
+	 * this part - the lookup - needs to run without locks
+	 * so that it can safely be called from within the notify handler.
+	 * notify calls _p9uproc, and fork and rfork call _p9uproc
+	 * in both parent and child, so if we're in a signal handler,
+	 * we should find something in the table.
+	 */
+	h = pid%PIDHASH;
+	for(i=0; i<PIDHASH; i++){
+		up = alluproc[h];
+		if(up == nil)
+			break;
+		if(allupid[h] == pid)
 			return up;
-		}
+		if(++h == PIDHASH)
+			h = 0;
 	}
 
-	up = mallocz(sizeof(Uproc), 1);
-	if(up == nil){
-if(0)print("again %d\n", pid);
-		unlock(&uproclock);
-		sleep(1000);
-		goto again;
-	}
+	if(inhandler)
+		sysfatal("did not find uproc in signal handler");
 
-againpipe:
-	if(pipe(up->pipe) < 0){
-if(0)print("againpipe %d\n", pid);
+	/* need to allocate */
+	while((up = mallocz(sizeof(Uproc), 1)) == nil)
 		sleep(1000);
-		goto againpipe;
-	}
 
-	up->pid = pid;
-	up->next = phash[pid%PIDHASH];
-	phash[pid%PIDHASH] = up;
-if(0)print("link %d\n", pid);
+	up = mallocz(sizeof(Uproc), 1);
+	lock(&uproclock);
+	h = pid%PIDHASH;
+	for(i=0; i<PIDHASH; i++){
+		if(alluproc[h]==T || alluproc[h]==nil){
+			alluproc[h] = up;
+			allupid[h] = pid;
+			return up;
+		}
+		if(++h == PIDHASH)
+			h = 0;
+	}
 	unlock(&uproclock);
-	return up;
+
+	/* out of pids! */
+	sysfatal("too many processes in uproc table");
+	return nil;
 }
 
 void
 _p9uprocdie(void)
 {
-	Uproc **l, *up;
-	int pid;
+	Uproc *up;
+	int pid, i, h;
 
 	pid = getpid();
-if(0)print("die %d\n", pid);
-	lock(&uproclock);
-	for(l=&phash[pid%33]; *l; l=&(*l)->next){
-		if((*l)->pid == pid){
-			up = *l;
-			*l = up->next;
-if(0)print("died %d\n", pid);
-			unlock(&uproclock);
-			close(up->pipe[0]);
-			close(up->pipe[1]);
+	h = pid%PIDHASH;
+	for(i=0; i<PIDHASH; i++){
+		up = alluproc[h];
+		if(up == nil)
+			break;
+		if(up == T)
+			continue;
+		if(allupid[h] == pid){
+			up = alluproc[h];
+			alluproc[h] = T;
 			free(up);
-			return;
+			allupid[h] = 0;
 		}
 	}
-if(0)print("not started %d\n", pid);
-	unlock(&uproclock);
 }
blob - 12edb0e4b9df34f2447bc5fd3cfb880264303c91
blob + 79a5e621a807ffd5cceafa3c19c96c499f399f2f
--- src/lib9/notify.c
+++ src/lib9/notify.c
@@ -49,7 +49,7 @@ notifysigf(int sig)
 	char tmp[64];
 	Uproc *up;
 
-	up = _p9uproc();
+	up = _p9uproc(1);
 	v = p9setjmp(up->notejb);
 	if(v == 0 && notifyf)
 		(*notifyf)(nil, _p9sigstr(sig, tmp));
@@ -68,6 +68,7 @@ notify(void (*f)(void*, char*))
 	int i;
 	struct sigaction sa;
 
+	_p9uproc(0);
 	memset(&sa, 0, sizeof sa);
 	if(f == 0)
 		sa.sa_handler = SIG_DFL;
@@ -90,7 +91,7 @@ noted(int v)
 {
 	Uproc *up;
 
-	up = _p9uproc();
+	up = _p9uproc(1);
 	p9longjmp(up->notejb, v==NCONT ? 2 : 1);
 	abort();
 	return 0;
blob - 651c48c1cca66d4bdffaa4df76e82a3e5bf842c2
blob + e64e9194f3ce007722cd24b76e3e4b2059f7c5b1
--- src/lib9/priv.c
+++ src/lib9/priv.c
@@ -26,7 +26,7 @@ privmem(int i)
 {
 	Uproc *up;
 
-	up = _p9uproc();
+	up = _p9uproc(0);
 	return &up->priv[i];
 }
 
blob - cf23a4e5ad63df9024dc09195b27dc7b8c0f56c1
blob + 2b2c1a19fa0d4b3d9538be23dd90936f755513d1
--- src/lib9/rendez.c
+++ src/lib9/rendez.c
@@ -12,7 +12,7 @@ rendezvous(ulong tag, ulong val)
 	ulong ret;
 	Uproc *t, *self, **l;
 
-	self = _p9uproc();
+	self = _p9uproc(0);
 	lock(&rendlock);
 	l = &rendhash[tag%RENDHASH];
 	for(t=*l; t; l=&t->rendhash, t=*l){
blob - f3a21928dd0278596dc931e5cd69f8727cb82758
blob + 21dc17e81ea579642d7b5ad3c3c2de6c79ca6f67
--- src/lib9/rfork.c
+++ src/lib9/rfork.c
@@ -1,5 +1,7 @@
-#define NOPLAN9DEFINES
-#include <lib9.h>
+#include <u.h>
+#include <libc.h>
+#include "9proc.h"
+#undef rfork
 
 int
 p9rfork(int flags)
@@ -14,6 +16,7 @@ p9rfork(int flags)
 			return -1;
 		}
 		pid = fork();
+		_p9uproc(0);
 		if(pid != 0)
 			return pid;
 	}