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 void
54 _procsleep(_Procrendez *r)
55 {
56 /* r is protected by r->l, which we hold */
57 pthread_cond_init(&r->cond, 0);
58 r->asleep = 1;
59 pthread_cond_wait(&r->cond, &r->l->mutex);
60 pthread_cond_destroy(&r->cond);
61 r->asleep = 0;
62 }
64 void
65 _procwakeup(_Procrendez *r)
66 {
67 if(r->asleep){
68 r->asleep = 0;
69 pthread_cond_signal(&r->cond);
70 }
71 }
73 void
74 _procwakeupandunlock(_Procrendez *r)
75 {
76 if(r->asleep){
77 r->asleep = 0;
78 pthread_cond_signal(&r->cond);
79 }
80 unlock(r->l);
81 }
83 static void
84 startprocfn(void *v)
85 {
86 void **a;
87 void (*fn)(void*);
88 Proc *p;
90 a = (void**)v;
91 fn = (void(*)(void*))a[0];
92 p = a[1];
93 free(a);
94 p->osprocid = pthread_self();
95 pthread_detach(p->osprocid);
97 (*fn)(p);
99 pthread_exit(0);
102 void
103 _procstart(Proc *p, void (*fn)(Proc*))
105 void **a;
107 a = malloc(2*sizeof a[0]);
108 if(a == nil)
109 sysfatal("_procstart malloc: %r");
110 a[0] = (void*)fn;
111 a[1] = p;
113 if(pthread_create(&p->osprocid, nil, (void*(*)(void*))startprocfn, (void*)a) < 0){
114 fprint(2, "pthread_create: %r\n");
115 abort();
119 static pthread_key_t prockey;
121 Proc*
122 _threadproc(void)
124 Proc *p;
126 p = pthread_getspecific(prockey);
127 return p;
130 void
131 _threadsetproc(Proc *p)
133 pthread_setspecific(prockey, p);
136 void
137 _pthreadinit(void)
139 static struct utsname un;
140 pthread_t id;
142 if(uname(&un) < 0)
143 fprint(2, "warning: uname failed: %r\n");
144 if(strcmp(un.sysname, "Linux") == 0){
145 /*
146 * Want to distinguish between the old LinuxThreads pthreads
147 * and the new NPTL implementation. NPTL uses much bigger
148 * thread IDs.
149 */
150 id = pthread_self();
151 if(*(ulong*)(void*)&id < 1024*1024)
152 sysfatal("cannot use LinuxThreads as pthread library; see %s/src/libthread/README.Linux", get9root());
154 pthread_key_create(&prockey, 0);
157 void
158 threadexitsall(char *msg)
160 exits(msg);
163 void
164 _threadpexit(void)
166 pthread_exit(0);