tadd pthread - plan9port - [fork] Plan 9 from user space
git clone git://src.adamsgaard.dk/plan9port
Log
Files
Refs
README
LICENSE
---
commit e7821682ea0105c74f00986131cf59b07d4966cc
parent 4fbe07e1db9282a09a3f021922a3e13346b5e932
Author: rsc 
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(-)
---
diff --git a/src/libthread/pthread.c b/src/libthread/pthread.c
t@@ -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;
+}