From 175b8a534ae5729ac10ea793410a40bfa4a30608 Mon Sep 17 00:00:00 2001 From: rsc Date: Wed, 21 Apr 2004 04:48:25 +0000 Subject: No more malloc or lock inside signal handlers. --- src/lib9/9proc.h | 5 +-- src/lib9/_p9proc.c | 110 ++++++++++++++++++++++++++++++++--------------------- src/lib9/notify.c | 5 ++- src/lib9/priv.c | 2 +- src/lib9/rendez.c | 2 +- src/lib9/rfork.c | 7 +++- 6 files changed, 77 insertions(+), 54 deletions(-) (limited to 'src/lib9') diff --git a/src/lib9/9proc.h b/src/lib9/9proc.h index 713b9558..663d65b6 100644 --- a/src/lib9/9proc.h +++ b/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); diff --git a/src/lib9/_p9proc.c b/src/lib9/_p9proc.c index 6e4010cd..374fb089 100644 --- a/src/lib9/_p9proc.c +++ b/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 #include #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; ipipe) < 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; inext){ - 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; inotejb); 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; diff --git a/src/lib9/priv.c b/src/lib9/priv.c index 651c48c1..e64e9194 100644 --- a/src/lib9/priv.c +++ b/src/lib9/priv.c @@ -26,7 +26,7 @@ privmem(int i) { Uproc *up; - up = _p9uproc(); + up = _p9uproc(0); return &up->priv[i]; } diff --git a/src/lib9/rendez.c b/src/lib9/rendez.c index cf23a4e5..2b2c1a19 100644 --- a/src/lib9/rendez.c +++ b/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){ diff --git a/src/lib9/rfork.c b/src/lib9/rfork.c index f3a21928..21dc17e8 100644 --- a/src/lib9/rfork.c +++ b/src/lib9/rfork.c @@ -1,5 +1,7 @@ -#define NOPLAN9DEFINES -#include +#include +#include +#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; } -- cgit v1.2.3