tadd pthread - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit e7821682ea0105c74f00986131cf59b07d4966cc
 (DIR) parent 4fbe07e1db9282a09a3f021922a3e13346b5e932
 (HTM) Author: rsc <devnull@localhost>
       Date:   Thu, 23 Sep 2004 19:03:46 +0000
       
       add pthread
       
       Diffstat:
         A src/libthread/pthread.c             |     164 +++++++++++++++++++++++++++++++
       
       1 file changed, 164 insertions(+), 0 deletions(-)
       ---
 (DIR) diff --git a/src/libthread/pthread.c b/src/libthread/pthread.c
       t@@ -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;
       +}