1 /*	Public domain	*/
2 
3 #ifndef _AGAR_CORE_THREADS_H_
4 #define _AGAR_CORE_THREADS_H_
5 
6 #ifdef AG_THREADS
7 
8 #include <agar/config/have_pthreads.h>
9 #ifdef HAVE_PTHREADS
10 #include <pthread.h>
11 #include <signal.h>
12 #include <stdio.h>
13 #include <string.h>
14 #else
15 # error "AG_THREADS option requires POSIX threads"
16 #endif
17 
18 typedef pthread_mutex_t AG_Mutex;
19 typedef pthread_mutexattr_t AG_MutexAttr;
20 typedef pthread_t AG_Thread;
21 typedef pthread_cond_t AG_Cond;
22 typedef pthread_key_t AG_ThreadKey;
23 
24 #ifdef _SGI_SOURCE
25 #define AG_MUTEX_INITIALIZER {{0}}
26 #else
27 #define AG_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
28 #endif
29 
30 #include <agar/core/begin.h>
31 __BEGIN_DECLS
32 extern pthread_mutexattr_t agRecursiveMutexAttr;
33 extern AG_Thread           agEventThread;
34 __END_DECLS
35 #include <agar/core/close.h>
36 
37 #define AG_ThreadSelf()			pthread_self()
38 #define AG_ThreadEqual(t1,t2)		pthread_equal((t1),(t2))
39 #define AG_ThreadExit(p)		pthread_exit(p)
40 #define AG_ThreadKeyGet(k)		pthread_getspecific(k)
41 #define AG_ThreadSigMask(how,n,o)	pthread_sigmask((how),(n),(o))
42 #define AG_ThreadKill(thread,signo)	(void)pthread_kill((thread),(signo))
43 #define AG_MutexTryLock(m)		pthread_mutex_trylock(m)
44 #define AG_CondWait(cd,m)		pthread_cond_wait(cd,m)
45 #define AG_CondTimedWait(cd,m,t)	pthread_cond_timedwait(cd,m,t)
46 
47 /*
48  * Thread interface
49  */
50 static __inline__ void
AG_ThreadCreate(AG_Thread * th,void * (* fn)(void *),void * arg)51 AG_ThreadCreate(AG_Thread *th, void *(*fn)(void *), void *arg)
52 {
53 	int rv;
54 	if ((rv = pthread_create(th, NULL, fn, arg)) != 0)
55 		AG_FatalError("pthread_create (%d)", rv);
56 }
57 static __inline__ int
AG_ThreadTryCreate(AG_Thread * th,void * (* fn)(void *),void * arg)58 AG_ThreadTryCreate(AG_Thread *th, void *(*fn)(void *), void *arg)
59 {
60 	int rv;
61 	if ((rv = pthread_create(th, NULL, fn, arg)) != 0) {
62 		AG_SetError("%s", AG_Strerror(rv));
63 		return (-1);
64 	}
65 	return (0);
66 }
67 static __inline__ void
AG_ThreadCancel(AG_Thread th)68 AG_ThreadCancel(AG_Thread th)
69 {
70 	if (pthread_cancel(th) != 0)
71 		AG_FatalError("pthread_cancel");
72 }
73 static __inline__ int
AG_ThreadTryCancel(AG_Thread th)74 AG_ThreadTryCancel(AG_Thread th)
75 {
76 	int rv;
77 	if ((rv = pthread_cancel(th)) != 0) {
78 		AG_SetError("%s", AG_Strerror(rv));
79 		return (-1);
80 	}
81 	return (0);
82 }
83 static __inline__ void
AG_ThreadJoin(AG_Thread th,void ** p)84 AG_ThreadJoin(AG_Thread th, void **p)
85 {
86 	if (pthread_join(th, p) != 0)
87 		AG_FatalError("pthread_join");
88 }
89 static __inline__ int
AG_ThreadTryJoin(AG_Thread th,void ** p)90 AG_ThreadTryJoin(AG_Thread th, void **p)
91 {
92 	int rv;
93 	if ((rv = pthread_join(th, p)) != 0) {
94 		AG_SetError("%s", AG_Strerror(rv));
95 		return (-1);
96 	}
97 	return (0);
98 }
99 
100 /*
101  * Mutex interface
102  */
103 static __inline__ void
AG_MutexInit(AG_Mutex * m)104 AG_MutexInit(AG_Mutex *m)
105 {
106 	if (pthread_mutex_init(m, NULL) != 0)
107 		AG_FatalError("pthread_mutex_init");
108 }
109 static __inline__ void
AG_MutexInitRecursive(AG_Mutex * m)110 AG_MutexInitRecursive(AG_Mutex *m)
111 {
112 	if (pthread_mutex_init(m, &agRecursiveMutexAttr) != 0)
113 		AG_FatalError("pthread_mutex_init(recursive)");
114 }
115 static __inline__ int
AG_MutexTryInit(AG_Mutex * m)116 AG_MutexTryInit(AG_Mutex *m)
117 {
118 	int rv;
119 	if ((rv = pthread_mutex_init(m, NULL)) != 0) {
120 		AG_SetError("%s", AG_Strerror(rv));
121 		return (-1);
122 	}
123 	return (0);
124 }
125 static __inline__ int
AG_MutexTryInitRecursive(AG_Mutex * m)126 AG_MutexTryInitRecursive(AG_Mutex *m)
127 {
128 	int rv;
129 	if ((rv = pthread_mutex_init(m, &agRecursiveMutexAttr)) != 0) {
130 		AG_SetError("%s", AG_Strerror(rv));
131 		return (-1);
132 	}
133 	return (0);
134 }
135 static __inline__ void
AG_MutexLock(AG_Mutex * m)136 AG_MutexLock(AG_Mutex *m)
137 {
138 	if (pthread_mutex_lock(m) != 0)
139 		AG_FatalError("pthread_mutex_lock");
140 }
141 static __inline__ void
AG_MutexUnlock(AG_Mutex * m)142 AG_MutexUnlock(AG_Mutex *m)
143 {
144 	if (pthread_mutex_unlock(m) != 0)
145 		AG_FatalError("pthread_mutex_unlock");
146 }
147 static __inline__ void
AG_MutexDestroy(AG_Mutex * m)148 AG_MutexDestroy(AG_Mutex *m)
149 {
150 	if (pthread_mutex_destroy(m) != 0)
151 		AG_FatalError("pthread_mutex_destroy");
152 }
153 
154 /*
155  * Condition variable interface
156  */
157 static __inline__ void
AG_CondInit(AG_Cond * cd)158 AG_CondInit(AG_Cond *cd)
159 {
160 	if (pthread_cond_init(cd, NULL) != 0)
161 		AG_FatalError("pthread_cond_init");
162 }
163 static __inline__ int
AG_CondTryInit(AG_Cond * cd)164 AG_CondTryInit(AG_Cond *cd)
165 {
166 	int rv;
167 	if ((rv = pthread_cond_init(cd, NULL)) != 0) {
168 		AG_SetError("%s", AG_Strerror(rv));
169 		return (-1);
170 	}
171 	return (0);
172 }
173 static __inline__ void
AG_CondDestroy(AG_Cond * cd)174 AG_CondDestroy(AG_Cond *cd)
175 {
176 	if (pthread_cond_destroy(cd) != 0)
177 		AG_FatalError("pthread_cond_destroy");
178 }
179 static __inline__ void
AG_CondBroadcast(AG_Cond * cd)180 AG_CondBroadcast(AG_Cond *cd)
181 {
182 	if (pthread_cond_broadcast(cd) != 0)
183 		AG_FatalError("pthread_cond_broadcast");
184 }
185 static __inline__ void
AG_CondSignal(AG_Cond * cd)186 AG_CondSignal(AG_Cond *cd)
187 {
188 	if (pthread_cond_signal(cd) != 0)
189 		AG_FatalError("pthread_cond_signal");
190 }
191 
192 /*
193  * Thread-local storage interface
194  */
195 static __inline__ void
AG_ThreadKeyCreate(AG_ThreadKey * k,void (* destructorFn)(void *))196 AG_ThreadKeyCreate(AG_ThreadKey *k, void (*destructorFn)(void *))
197 {
198 	if (pthread_key_create(k,destructorFn) != 0)
199 		AG_FatalError("pthread_key_create");
200 }
201 static __inline__ int
AG_ThreadKeyTryCreate(AG_ThreadKey * k,void (* destructorFn)(void *))202 AG_ThreadKeyTryCreate(AG_ThreadKey *k, void (*destructorFn)(void *))
203 {
204 	int rv;
205 	if ((rv = pthread_key_create(k,destructorFn)) != 0) {
206 		AG_SetError("%s", AG_Strerror(rv));
207 		return (-1);
208 	}
209 	return (0);
210 }
211 static __inline__ void
AG_ThreadKeyDelete(AG_ThreadKey k)212 AG_ThreadKeyDelete(AG_ThreadKey k)
213 {
214 	if (pthread_key_delete(k) != 0)
215 		AG_FatalError("pthread_key_delete");
216 }
217 static __inline__ int
AG_ThreadKeyTryDelete(AG_ThreadKey k)218 AG_ThreadKeyTryDelete(AG_ThreadKey k)
219 {
220 	int rv;
221 	if ((rv = pthread_key_delete(k)) != 0) {
222 		AG_SetError("%s", AG_Strerror(rv));
223 		return (-1);
224 	}
225 	return (0);
226 }
227 static __inline__ void
AG_ThreadKeySet(AG_ThreadKey k,const void * p)228 AG_ThreadKeySet(AG_ThreadKey k, const void *p)
229 {
230 	if (pthread_setspecific(k, p) != 0)
231 		AG_FatalError("pthread_setspecific");
232 }
233 static __inline__ int
AG_ThreadKeyTrySet(AG_ThreadKey k,const void * p)234 AG_ThreadKeyTrySet(AG_ThreadKey k, const void *p)
235 {
236 	int rv;
237 	if ((rv = pthread_setspecific(k, p)) != 0) {
238 		AG_SetError("%s", AG_Strerror(rv));
239 		return (-1);
240 	}
241 	return (0);
242 }
243 
244 #else /* !AG_THREADS */
245 
246 typedef void *AG_Mutex;
247 typedef void *AG_Thread;
248 typedef void *AG_Cond;
249 typedef void *AG_MutexAttr;
250 typedef int   AG_ThreadKey;
251 
252 #define AG_MUTEX_INITIALIZER 0
253 #define AG_COND_INITIALIZER 0
254 
255 #define AG_MutexInit(m)
256 #define AG_MutexInitRecursive(m)
257 #define AG_MutexDestroy(m)
258 #define AG_MutexLock(m)
259 #define AG_MutexUnlock(m)
260 #define AG_CondInit(cd)
261 #define AG_CondDestroy(cd)
262 #define AG_CondBroadcast(cd)
263 #define AG_CondSignal(cd)
264 #define AG_CondWait(cd,m)
265 #define AG_CondTimedWait(cd,m,t)
266 
AG_MutexTryInit(AG_Mutex * mu)267 static __inline__ int AG_MutexTryInit(AG_Mutex *mu) { return (0); }
AG_MutexTryInitRecursive(AG_Mutex * mu)268 static __inline__ int AG_MutexTryInitRecursive(AG_Mutex *mu) { return (0); }
AG_MutexTryLock(AG_Mutex * mu)269 static __inline__ int AG_MutexTryLock(AG_Mutex *mu) { return (0); }
270 
271 #undef HAVE_PTHREADS
272 #endif /* AG_THREADS */
273 
274 #endif /* _AGAR_CORE_THREADS_H_ */
275