pthread.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 }