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