commit - ac0e2db600593d5b30550453b78874bfa0611751
commit + 175b8a534ae5729ac10ea793410a40bfa4a30608
blob - 713b9558d527438137d385224a3582f645889f41
blob + 663d65b6bee3f48695cfb0611cf91970825703d6
--- src/lib9/9proc.h
+++ src/lib9/9proc.h
{
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;
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
+/*
+ * 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
char tmp[64];
Uproc *up;
- up = _p9uproc();
+ up = _p9uproc(1);
v = p9setjmp(up->notejb);
if(v == 0 && notifyf)
(*notifyf)(nil, _p9sigstr(sig, tmp));
int i;
struct sigaction sa;
+ _p9uproc(0);
memset(&sa, 0, sizeof sa);
if(f == 0)
sa.sa_handler = SIG_DFL;
{
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
{
Uproc *up;
- up = _p9uproc();
+ up = _p9uproc(0);
return &up->priv[i];
}
blob - cf23a4e5ad63df9024dc09195b27dc7b8c0f56c1
blob + 2b2c1a19fa0d4b3d9538be23dd90936f755513d1
--- src/lib9/rendez.c
+++ src/lib9/rendez.c
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
-#define NOPLAN9DEFINES
-#include <lib9.h>
+#include <u.h>
+#include <libc.h>
+#include "9proc.h"
+#undef rfork
int
p9rfork(int flags)
return -1;
}
pid = fork();
+ _p9uproc(0);
if(pid != 0)
return pid;
}