No more malloc or lock inside signal handlers.
This commit is contained in:
parent
ac0e2db600
commit
175b8a534a
6 changed files with 78 additions and 55 deletions
|
|
@ -2,15 +2,12 @@ enum
|
||||||
{
|
{
|
||||||
NPRIV = 16,
|
NPRIV = 16,
|
||||||
RENDHASH = 33,
|
RENDHASH = 33,
|
||||||
PIDHASH = 33,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct Uproc Uproc;
|
typedef struct Uproc Uproc;
|
||||||
struct Uproc
|
struct Uproc
|
||||||
{
|
{
|
||||||
Uproc *next;
|
|
||||||
int pid;
|
int pid;
|
||||||
int pipe[2];
|
|
||||||
int state;
|
int state;
|
||||||
void *priv[NPRIV];
|
void *priv[NPRIV];
|
||||||
ulong rendval;
|
ulong rendval;
|
||||||
|
|
@ -19,5 +16,5 @@ struct Uproc
|
||||||
p9jmp_buf notejb;
|
p9jmp_buf notejb;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Uproc *_p9uproc(void);
|
extern Uproc *_p9uproc(int);
|
||||||
extern void _p9uprocdie(void);
|
extern void _p9uprocdie(void);
|
||||||
|
|
|
||||||
|
|
@ -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 <u.h>
|
||||||
#include <libc.h>
|
#include <libc.h>
|
||||||
#include "9proc.h"
|
#include "9proc.h"
|
||||||
|
|
||||||
|
enum { PIDHASH = 1021 };
|
||||||
|
|
||||||
|
#define T ((void*)-1)
|
||||||
|
static Uproc *alluproc[PIDHASH];
|
||||||
|
static int allupid[PIDHASH];
|
||||||
static Lock uproclock;
|
static Lock uproclock;
|
||||||
static Uproc *phash[PIDHASH];
|
|
||||||
|
|
||||||
Uproc*
|
Uproc*
|
||||||
_p9uproc(void)
|
_p9uproc(int inhandler)
|
||||||
{
|
{
|
||||||
/* for now, assume getpid is fast or cached */
|
int i, h, pid;
|
||||||
int pid;
|
|
||||||
Uproc *up;
|
Uproc *up;
|
||||||
|
|
||||||
|
/* for now, assume getpid is fast or cached */
|
||||||
pid = getpid();
|
pid = getpid();
|
||||||
again:
|
|
||||||
if(0)print("find %d\n", pid);
|
/*
|
||||||
lock(&uproclock);
|
* this part - the lookup - needs to run without locks
|
||||||
for(up=phash[pid%PIDHASH]; up; up=up->next){
|
* so that it can safely be called from within the notify handler.
|
||||||
if(up->pid == pid){
|
* notify calls _p9uproc, and fork and rfork call _p9uproc
|
||||||
if(0)print("found %d\n", pid);
|
* in both parent and child, so if we're in a signal handler,
|
||||||
unlock(&uproclock);
|
* 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;
|
return up;
|
||||||
|
if(++h == PIDHASH)
|
||||||
|
h = 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
if(inhandler)
|
||||||
|
sysfatal("did not find uproc in signal handler");
|
||||||
|
|
||||||
|
/* need to allocate */
|
||||||
|
while((up = mallocz(sizeof(Uproc), 1)) == nil)
|
||||||
|
sleep(1000);
|
||||||
|
|
||||||
up = mallocz(sizeof(Uproc), 1);
|
up = mallocz(sizeof(Uproc), 1);
|
||||||
if(up == nil){
|
lock(&uproclock);
|
||||||
if(0)print("again %d\n", pid);
|
h = pid%PIDHASH;
|
||||||
unlock(&uproclock);
|
for(i=0; i<PIDHASH; i++){
|
||||||
sleep(1000);
|
if(alluproc[h]==T || alluproc[h]==nil){
|
||||||
goto again;
|
alluproc[h] = up;
|
||||||
}
|
allupid[h] = pid;
|
||||||
|
|
||||||
againpipe:
|
|
||||||
if(pipe(up->pipe) < 0){
|
|
||||||
if(0)print("againpipe %d\n", pid);
|
|
||||||
sleep(1000);
|
|
||||||
goto againpipe;
|
|
||||||
}
|
|
||||||
|
|
||||||
up->pid = pid;
|
|
||||||
up->next = phash[pid%PIDHASH];
|
|
||||||
phash[pid%PIDHASH] = up;
|
|
||||||
if(0)print("link %d\n", pid);
|
|
||||||
unlock(&uproclock);
|
|
||||||
return up;
|
return up;
|
||||||
}
|
}
|
||||||
|
if(++h == PIDHASH)
|
||||||
|
h = 0;
|
||||||
|
}
|
||||||
|
unlock(&uproclock);
|
||||||
|
|
||||||
|
/* out of pids! */
|
||||||
|
sysfatal("too many processes in uproc table");
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_p9uprocdie(void)
|
_p9uprocdie(void)
|
||||||
{
|
{
|
||||||
Uproc **l, *up;
|
Uproc *up;
|
||||||
int pid;
|
int pid, i, h;
|
||||||
|
|
||||||
pid = getpid();
|
pid = getpid();
|
||||||
if(0)print("die %d\n", pid);
|
h = pid%PIDHASH;
|
||||||
lock(&uproclock);
|
for(i=0; i<PIDHASH; i++){
|
||||||
for(l=&phash[pid%33]; *l; l=&(*l)->next){
|
up = alluproc[h];
|
||||||
if((*l)->pid == pid){
|
if(up == nil)
|
||||||
up = *l;
|
break;
|
||||||
*l = up->next;
|
if(up == T)
|
||||||
if(0)print("died %d\n", pid);
|
continue;
|
||||||
unlock(&uproclock);
|
if(allupid[h] == pid){
|
||||||
close(up->pipe[0]);
|
up = alluproc[h];
|
||||||
close(up->pipe[1]);
|
alluproc[h] = T;
|
||||||
free(up);
|
free(up);
|
||||||
return;
|
allupid[h] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(0)print("not started %d\n", pid);
|
|
||||||
unlock(&uproclock);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ notifysigf(int sig)
|
||||||
char tmp[64];
|
char tmp[64];
|
||||||
Uproc *up;
|
Uproc *up;
|
||||||
|
|
||||||
up = _p9uproc();
|
up = _p9uproc(1);
|
||||||
v = p9setjmp(up->notejb);
|
v = p9setjmp(up->notejb);
|
||||||
if(v == 0 && notifyf)
|
if(v == 0 && notifyf)
|
||||||
(*notifyf)(nil, _p9sigstr(sig, tmp));
|
(*notifyf)(nil, _p9sigstr(sig, tmp));
|
||||||
|
|
@ -68,6 +68,7 @@ notify(void (*f)(void*, char*))
|
||||||
int i;
|
int i;
|
||||||
struct sigaction sa;
|
struct sigaction sa;
|
||||||
|
|
||||||
|
_p9uproc(0);
|
||||||
memset(&sa, 0, sizeof sa);
|
memset(&sa, 0, sizeof sa);
|
||||||
if(f == 0)
|
if(f == 0)
|
||||||
sa.sa_handler = SIG_DFL;
|
sa.sa_handler = SIG_DFL;
|
||||||
|
|
@ -90,7 +91,7 @@ noted(int v)
|
||||||
{
|
{
|
||||||
Uproc *up;
|
Uproc *up;
|
||||||
|
|
||||||
up = _p9uproc();
|
up = _p9uproc(1);
|
||||||
p9longjmp(up->notejb, v==NCONT ? 2 : 1);
|
p9longjmp(up->notejb, v==NCONT ? 2 : 1);
|
||||||
abort();
|
abort();
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ privmem(int i)
|
||||||
{
|
{
|
||||||
Uproc *up;
|
Uproc *up;
|
||||||
|
|
||||||
up = _p9uproc();
|
up = _p9uproc(0);
|
||||||
return &up->priv[i];
|
return &up->priv[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ rendezvous(ulong tag, ulong val)
|
||||||
ulong ret;
|
ulong ret;
|
||||||
Uproc *t, *self, **l;
|
Uproc *t, *self, **l;
|
||||||
|
|
||||||
self = _p9uproc();
|
self = _p9uproc(0);
|
||||||
lock(&rendlock);
|
lock(&rendlock);
|
||||||
l = &rendhash[tag%RENDHASH];
|
l = &rendhash[tag%RENDHASH];
|
||||||
for(t=*l; t; l=&t->rendhash, t=*l){
|
for(t=*l; t; l=&t->rendhash, t=*l){
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
#define NOPLAN9DEFINES
|
#include <u.h>
|
||||||
#include <lib9.h>
|
#include <libc.h>
|
||||||
|
#include "9proc.h"
|
||||||
|
#undef rfork
|
||||||
|
|
||||||
int
|
int
|
||||||
p9rfork(int flags)
|
p9rfork(int flags)
|
||||||
|
|
@ -14,6 +16,7 @@ p9rfork(int flags)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
pid = fork();
|
pid = fork();
|
||||||
|
_p9uproc(0);
|
||||||
if(pid != 0)
|
if(pid != 0)
|
||||||
return pid;
|
return pid;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue