add pthread
This commit is contained in:
parent
4fbe07e1db
commit
e7821682ea
1 changed files with 164 additions and 0 deletions
164
src/libthread/pthread.c
Normal file
164
src/libthread/pthread.c
Normal file
|
|
@ -0,0 +1,164 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include "threadimpl.h"
|
||||||
|
|
||||||
|
static int multi;
|
||||||
|
static Proc *theproc;
|
||||||
|
static pthread_key_t key;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called before we go multiprocess.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
_threadmultiproc(void)
|
||||||
|
{
|
||||||
|
if(multi == 0){
|
||||||
|
multi = 1;
|
||||||
|
pthread_key_create(&key, 0);
|
||||||
|
_threadsetproc(theproc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the proc for the current pthread.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
_threadsetproc(Proc *p)
|
||||||
|
{
|
||||||
|
if(!multi){
|
||||||
|
theproc = p;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pthread_setspecific(key, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the proc for the current pthread.
|
||||||
|
*/
|
||||||
|
Proc*
|
||||||
|
_threadgetproc(void)
|
||||||
|
{
|
||||||
|
if(!multi)
|
||||||
|
return theproc;
|
||||||
|
|
||||||
|
return pthread_getspecific(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called to associate p with the current pthread.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
_threadinitproc(Proc *p)
|
||||||
|
{
|
||||||
|
p->pthreadid = pthread_self();
|
||||||
|
_threadsetproc(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called to exit the current pthread.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
_threadexitproc(char *exitstr)
|
||||||
|
{
|
||||||
|
pthread_exit(nil);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called to exit all pthreads.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
_threadexitallproc(char *exitstr)
|
||||||
|
{
|
||||||
|
exits(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called to poll for any kids of this pthread.
|
||||||
|
* Wait messages aren't restricted to a particular
|
||||||
|
* pthread, so we have a separate proc responsible
|
||||||
|
* for them. So this is a no-op.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
_threadwaitkids(Proc *p)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Separate process to wait for child messages.
|
||||||
|
*/
|
||||||
|
Channel *_threadexecchan;
|
||||||
|
void
|
||||||
|
_threadwaitproc(void *v)
|
||||||
|
{
|
||||||
|
Channel *c;
|
||||||
|
Waitmsg *w;
|
||||||
|
sigset_t none;
|
||||||
|
|
||||||
|
sigemptyset(&none);
|
||||||
|
pthread_sigmask(SIG_SETMASK, &none, 0);
|
||||||
|
|
||||||
|
USED(v);
|
||||||
|
|
||||||
|
for(;;){
|
||||||
|
w = wait();
|
||||||
|
if(w == nil){
|
||||||
|
if(errno == ECHILD)
|
||||||
|
recvul(_threadexecchan);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if((c = _threadwaitchan) != nil)
|
||||||
|
sendp(c, w);
|
||||||
|
else
|
||||||
|
free(w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called before the first exec.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
_threadfirstexec(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_threadmaininit(void)
|
||||||
|
{
|
||||||
|
_threadexecchan = chancreate(sizeof(ulong), 1);
|
||||||
|
proccreate(_threadwaitproc, nil, 32*1024);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sleazy: decrement threadnprocs so that
|
||||||
|
* the existence of the _threadwaitproc proc
|
||||||
|
* doesn't keep us from exiting.
|
||||||
|
*/
|
||||||
|
lock(&_threadpq.lock);
|
||||||
|
--_threadnprocs;
|
||||||
|
/* print("change %d -> %d\n", _threadnprocs+1, _threadnprocs); */
|
||||||
|
unlock(&_threadpq.lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_threadafterexec(void)
|
||||||
|
{
|
||||||
|
nbsendul(_threadexecchan, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called to start a new proc.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
_threadstartproc(Proc *p)
|
||||||
|
{
|
||||||
|
Proc *np;
|
||||||
|
pthread_t tid;
|
||||||
|
sigset_t all;
|
||||||
|
|
||||||
|
np = p->newproc;
|
||||||
|
sigfillset(&all);
|
||||||
|
pthread_sigmask(SIG_SETMASK, &all, nil);
|
||||||
|
if(pthread_create(&tid, nil, (void*(*)(void*))_threadscheduler,
|
||||||
|
np) < 0)
|
||||||
|
sysfatal("pthread_create: %r");
|
||||||
|
np->pthreadid = tid;
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue