From e7821682ea0105c74f00986131cf59b07d4966cc Mon Sep 17 00:00:00 2001 From: rsc Date: Thu, 23 Sep 2004 19:03:46 +0000 Subject: add pthread --- src/libthread/pthread.c | 164 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 src/libthread/pthread.c (limited to 'src/libthread') diff --git a/src/libthread/pthread.c b/src/libthread/pthread.c new file mode 100644 index 00000000..b2c1c026 --- /dev/null +++ b/src/libthread/pthread.c @@ -0,0 +1,164 @@ +#include +#include +#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; +} -- cgit v1.2.3