URI:
       tpthread.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tpthread.c (3323B)
       ---
            1 #include "threadimpl.h"
            2 
            3 #undef exits
            4 #undef _exits
            5 
            6 static pthread_mutex_t initmutex = PTHREAD_MUTEX_INITIALIZER;
            7 
            8 static void
            9 lockinit(Lock *lk)
           10 {
           11         pthread_mutexattr_t attr;
           12 
           13         pthread_mutex_lock(&initmutex);
           14         if(lk->init == 0){
           15                 pthread_mutexattr_init(&attr);
           16                 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
           17                 pthread_mutex_init(&lk->mutex, &attr);
           18                 pthread_mutexattr_destroy(&attr);
           19                 lk->init = 1;
           20         }
           21         pthread_mutex_unlock(&initmutex);
           22 }
           23 
           24 int
           25 _threadlock(Lock *lk, int block, ulong pc)
           26 {
           27         int r;
           28 
           29         if(!lk->init)
           30                 lockinit(lk);
           31         if(block){
           32                 if(pthread_mutex_lock(&lk->mutex) != 0)
           33                         abort();
           34                 return 1;
           35         }else{
           36                 r = pthread_mutex_trylock(&lk->mutex);
           37                 if(r == 0)
           38                         return 1;
           39                 if(r == EBUSY)
           40                         return 0;
           41                 abort();
           42                 return 0;
           43         }
           44 }
           45 
           46 void
           47 _threadunlock(Lock *lk, ulong pc)
           48 {
           49         if(pthread_mutex_unlock(&lk->mutex) != 0)
           50                 abort();
           51 }
           52 
           53 /* note: _procsleep can have spurious wakeups, like pthread_cond_wait */
           54 void
           55 _procsleep(_Procrendez *r)
           56 {
           57         /* r is protected by r->l, which we hold */
           58         pthread_cond_init(&r->cond, 0);
           59         r->asleep = 1;
           60         if(pthread_cond_wait(&r->cond, &r->l->mutex) != 0)
           61                 sysfatal("pthread_cond_wait: %r");
           62         pthread_cond_destroy(&r->cond);
           63         r->asleep = 0;
           64 }
           65 
           66 void
           67 _procwakeup(_Procrendez *r)
           68 {
           69         if(r->asleep){
           70                 r->asleep = 0;
           71                 pthread_cond_signal(&r->cond);
           72         }
           73 }
           74 
           75 void
           76 _procwakeupandunlock(_Procrendez *r)
           77 {
           78         if(r->asleep){
           79                 r->asleep = 0;
           80                 pthread_cond_signal(&r->cond);
           81         }
           82         unlock(r->l);
           83 }
           84 
           85 static void
           86 startprocfn(void *v)
           87 {
           88         void **a;
           89         void (*fn)(void*);
           90         Proc *p;
           91 
           92         a = (void**)v;
           93         fn = (void(*)(void*))a[0];
           94         p = a[1];
           95         free(a);
           96         p->osprocid = pthread_self();
           97         pthread_detach(p->osprocid);
           98 
           99         (*fn)(p);
          100 
          101         pthread_exit(0);
          102 }
          103 
          104 static void
          105 startpthreadfn(void *v)
          106 {
          107         void **a;
          108         Proc *p;
          109         _Thread *t;
          110 
          111         a = (void**)v;
          112         p = a[0];
          113         t = a[1];
          114         free(a);
          115         t->osprocid = pthread_self();
          116         pthread_detach(t->osprocid);
          117         _threadpthreadmain(p, t);
          118         pthread_exit(0);
          119 }
          120 
          121 void
          122 _procstart(Proc *p, void (*fn)(Proc*))
          123 {
          124         void **a;
          125 
          126         a = malloc(2*sizeof a[0]);
          127         if(a == nil)
          128                 sysfatal("_procstart malloc: %r");
          129         a[0] = (void*)fn;
          130         a[1] = p;
          131 
          132         if(pthread_create(&p->osprocid, nil, (void*(*)(void*))startprocfn, (void*)a) < 0){
          133                 fprint(2, "pthread_create: %r\n");
          134                 abort();
          135         }
          136 }
          137 
          138 void
          139 _threadpthreadstart(Proc *p, _Thread *t)
          140 {
          141         void **a;
          142 
          143         a = malloc(3*sizeof a[0]);
          144         if(a == nil)
          145                 sysfatal("_pthreadstart malloc: %r");
          146         a[0] = p;
          147         a[1] = t;
          148         if(pthread_create(&t->osprocid, nil, (void*(*)(void*))startpthreadfn, (void*)a) < 0){
          149                 fprint(2, "pthread_create: %r\n");
          150                 abort();
          151         }
          152 }
          153 
          154 static pthread_key_t prockey;
          155 
          156 Proc*
          157 _threadproc(void)
          158 {
          159         Proc *p;
          160 
          161         p = pthread_getspecific(prockey);
          162         return p;
          163 }
          164 
          165 void
          166 _threadsetproc(Proc *p)
          167 {
          168         pthread_setspecific(prockey, p);
          169 }
          170 
          171 void
          172 _pthreadinit(void)
          173 {
          174         static struct utsname un;
          175         pthread_t id;
          176 
          177         if(uname(&un) < 0)
          178                 fprint(2, "warning: uname failed: %r\n");
          179         if(strcmp(un.sysname, "Linux") == 0){
          180                 /*
          181                  * Want to distinguish between the old LinuxThreads pthreads
          182                  * and the new NPTL implementation.  NPTL uses much bigger
          183                  * thread IDs.
          184                  */
          185                 id = pthread_self();
          186                 if(*(ulong*)(void*)&id < 1024*1024)
          187                         sysfatal("cannot use LinuxThreads as pthread library; see %s/src/libthread/README.Linux", get9root());
          188         }
          189         pthread_key_create(&prockey, 0);
          190 }
          191 
          192 void
          193 threadexitsall(char *msg)
          194 {
          195         exits(msg);
          196 }
          197 
          198 void
          199 _threadpexit(void)
          200 {
          201         pthread_exit(0);
          202 }