starting to work on Linux

This commit is contained in:
rsc 2004-12-27 18:21:58 +00:00
parent e127e40bb1
commit 955a2ca78d
5 changed files with 80 additions and 19 deletions

View file

@ -87,6 +87,7 @@ _procsleep(_Procrendez *r)
* unlock the vouslock so our waker can wake us,
* and then suspend.
*/
again:
r->asleep = 1;
r->pid = getpid();
@ -101,9 +102,13 @@ _procsleep(_Procrendez *r)
/*
* We're awake. Make USR1 not interrupt system calls.
*/
ignusr1(1);
assert(r->asleep == 0);
lock(r->l);
ignusr1(1);
if(r->asleep && r->pid == getpid()){
print("resleep %d\n", getpid());
/* Didn't really wake up - signal from something else */
goto again;
}
}
void
@ -233,6 +238,7 @@ static char *threadexitsmsg;
void
sigusr2handler(int s)
{
print("%d usr2 %d\n", time(0), getpid());
if(threadexitsmsg)
_exits(threadexitsmsg);
}
@ -259,6 +265,35 @@ threadexitsall(char *msg)
exits(msg);
}
/*
* exec - need to arrange for wait proc to run
* the execs so it gets the wait messages
*/
int
_runthreadspawn(int *fd, char *cmd, char **argv)
{
Execjob e;
int pid;
e.fd = fd;
e.cmd = cmd;
e.argv = argv;
e.c = chancreate(sizeof(ulong), 0);
print("%d run\n", time(0));
qlock(&_threadexeclock);
sendp(_threadexecchan, &e);
print("%d sent\n", time(0));
while(_threadexecproc == nil)
yield();
kill(_threadexecproc->osprocid, SIGUSR2);
print("%d killed\n", time(0));
pid = recvul(e.c);
qunlock(&_threadexeclock);
print("%d ran\n", time(0));
return pid;
}
/*
* per-process data, indexed by pid
*

View file

@ -6,26 +6,36 @@
static Lock thewaitlock;
static Channel *thewaitchan;
static Channel *dowaitchan;
static Channel *execchan;
Channel *_dowaitchan;
Channel *_threadexecchan;
Proc *_threadexecproc;
QLock _threadexeclock;
static void
execthread(void *v)
{
Execjob *e;
USED(v);
while((e = recvp(_threadexecchan)) != nil){
print("%d doexec pid %d\n", time(0), getpid());
sendul(e->c, _threadspawn(e->fd, e->cmd, e->argv));
}
}
static void
waitproc(void *v)
{
Channel *c;
Waitmsg *w;
Execjob *e;
_threadsetsysproc();
_threadexecproc = proc();
threadcreate(execthread, nil, 65536);
for(;;){
for(;;){
while((e = nbrecvp(execchan)) != nil)
sendul(e->c, _threadspawn(e->fd, e->cmd, e->argv));
if((w = wait()) != nil)
break;
while((w = wait()) == nil)
if(errno == ECHILD)
recvul(dowaitchan);
}
recvul(_dowaitchan);
if((c = thewaitchan) != nil)
sendp(c, w);
else
@ -94,20 +104,20 @@ _threadspawn(int fd[3], char *cmd, char *argv[])
close(fd[1]);
if(fd[2] != fd[1] && fd[2] != fd[0])
close(fd[2]);
channbsendul(dowaitchan, 1);
channbsendul(_dowaitchan, 1);
return pid;
}
int
threadspawn(int fd[3], char *cmd, char *argv[])
{
if(dowaitchan == nil){
if(_dowaitchan == nil){
lock(&thewaitlock);
if(dowaitchan == nil){
dowaitchan = chancreate(sizeof(ulong), 1);
chansetname(dowaitchan, "dowaitchan");
execchan = chancreate(sizeof(void*), 0);
chansetname(execchan, "execchan");
if(_dowaitchan == nil){
_dowaitchan = chancreate(sizeof(ulong), 1);
chansetname(_dowaitchan, "dowaitchan");
_threadexecchan = chancreate(sizeof(void*), 1);
chansetname(_threadexecchan, "execchan");
proccreate(waitproc, nil, STACK);
}
unlock(&thewaitlock);

View file

@ -0,0 +1,8 @@
<$PLAN9/src/mkhdr
SHORTLIB=thread 9
OFILES=
TARG=tprimes tspawn tspawnloop
<$PLAN9/src/mkmany

View file

@ -184,7 +184,9 @@ scheduler(Proc *p)
if(p->nthread == 0)
goto Out;
p->runrend.l = &p->lock;
print("sleep for jobs %d\n", getpid());
_procsleep(&p->runrend);
print("wake from jobs %d\n", getpid());
}
delthread(&p->runqueue, t);
unlock(&p->lock);

View file

@ -5,6 +5,8 @@ typedef struct Execjob Execjob;
typedef struct Proc Proc;
typedef struct _Procrendez _Procrendez;
typedef struct Jmp Jmp;
struct Jmp
{
@ -88,6 +90,10 @@ struct Proc
extern Proc *_threadprocs;
extern Lock _threadprocslock;
extern Proc *_threadexecproc;
extern Channel *_threadexecchan;
extern QLock _threadexeclock;
extern Channel *_dowaitchan;
extern void _procstart(Proc*, void (*fn)(Proc*));
extern _Thread *_threadcreate(Proc*, void(*fn)(void*), void*, uint);