Blob


1 #include "threadimpl.h"
3 #undef exits
4 #undef _exits
6 static pthread_mutex_t initmutex = PTHREAD_MUTEX_INITIALIZER;
8 static void
9 lockinit(Lock *lk)
10 {
11 pthread_mutexattr_t attr;
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 }
24 int
25 _threadlock(Lock *lk, int block, ulong pc)
26 {
27 int r;
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 }
46 void
47 _threadunlock(Lock *lk, ulong pc)
48 {
49 if(pthread_mutex_unlock(&lk->mutex) != 0)
50 abort();
51 }
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 }
66 void
67 _procwakeup(_Procrendez *r)
68 {
69 if(r->asleep){
70 r->asleep = 0;
71 pthread_cond_signal(&r->cond);
72 }
73 }
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 }
85 static void
86 startprocfn(void *v)
87 {
88 void **a;
89 void (*fn)(void*);
90 Proc *p;
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);
99 (*fn)(p);
101 pthread_exit(0);
104 static void
105 startpthreadfn(void *v)
107 void **a;
108 Proc *p;
109 _Thread *t;
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);
121 void
122 _procstart(Proc *p, void (*fn)(Proc*))
124 void **a;
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;
132 if(pthread_create(&p->osprocid, nil, (void*(*)(void*))startprocfn, (void*)a) < 0){
133 fprint(2, "pthread_create: %r\n");
134 abort();
138 void
139 _threadpthreadstart(Proc *p, _Thread *t)
141 void **a;
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();
154 static pthread_key_t prockey;
156 Proc*
157 _threadproc(void)
159 Proc *p;
161 p = pthread_getspecific(prockey);
162 return p;
165 void
166 _threadsetproc(Proc *p)
168 pthread_setspecific(prockey, p);
171 void
172 _pthreadinit(void)
174 static struct utsname un;
175 pthread_t id;
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());
189 pthread_key_create(&prockey, 0);
192 void
193 threadexitsall(char *msg)
195 exits(msg);
198 void
199 _threadpexit(void)
201 pthread_exit(0);