Add missing declaration for make_bigz
[sxemacs] / src / semaphore.h
1 /* semaphore.h - declarations for multi-threaded code
2
3    Copyright (C) 2006 Sebastian Freundt
4
5 This file is part of SXEmacs
6
7 SXEmacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 SXEmacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program.  If not, see <http://www.gnu.org/licenses/>. */
19
20
21 /* Synched up with: Not in FSF. */
22
23 #ifndef INCLUDED_semaphore_h_
24 #define INCLUDED_semaphore_h_
25
26 #if defined(HAVE_THREADS)
27 #include <pthread.h>
28 \f
29 /* decouple ordinary pthread mtxes */
30 #define sxe_thread_t    pthread_t
31 #define sxe_mutex_t     pthread_mutex_t
32
33 typedef void*(*sxe_thread_f)(void*);
34
35 #define SXE_MUTEX_INIT(_mtx)    pthread_mutex_init(_mtx, NULL)
36 #define SXE_MUTEX_FINI(_mtx)    pthread_mutex_destroy(_mtx)
37 #define SXE_MUTEX_LOCK(_mtx)    pthread_mutex_lock(_mtx)
38 #define SXE_MUTEX_UNLOCK(_mtx)  pthread_mutex_unlock(_mtx)
39
40 #define WITH_SXE_MUTEX(_mtx, args...)   \
41         SXE_MUTEX_LOCK(_mtx);           \
42         args;                           \
43         SXE_MUTEX_UNLOCK(_mtx);
44
45 \f
46 #define SXE_MSEMAPH_MAX_CONDITIONS      4
47
48 typedef struct sxe_semaphore_s *sxe_semaphore_t;
49 typedef struct sxe_msemaphore_s *sxe_msemaphore_t;
50 typedef struct sxe_refcounter_s *sxe_refcounter_t;
51
52 struct sxe_semaphore_s {
53         pthread_mutex_t mtx;
54         pthread_cond_t  cnd;
55         int generation;
56 };
57
58 struct sxe_msemaphore_s {
59         pthread_mutex_t mtx;
60         pthread_cond_t cnd[SXE_MSEMAPH_MAX_CONDITIONS];
61         int num_cnd;
62         int generation;
63 };
64
65 /* a thread-safe reference counter */
66 struct sxe_refcounter_s {
67         pthread_mutex_t mtx;
68         int refcnt;
69 };
70
71 #define SXE_SEMAPH_MUTEX(_sem)          ((_sem)->mtx)
72 #define SXE_SEMAPH_COND(_sem)           ((_sem)->cnd)
73 #define SXE_MSEMAPH_MUTEX(_sem)         ((_sem)->mtx)
74 #define SXE_MSEMAPH_COND(_sem, _idx)    ((_sem)->cnd[(_idx)])
75
76 extern_inline void sxe_semaphore_init(sxe_semaphore_t);
77 extern_inline void sxe_msemaphore_init(sxe_msemaphore_t);
78 extern_inline void sxe_semaphore_finish(sxe_semaphore_t);
79 extern_inline void sxe_msemaphore_finish(sxe_msemaphore_t);
80 extern_inline void sxe_semaphore_trigger(sxe_semaphore_t);
81 extern_inline void sxe_msemaphore_trigger(sxe_msemaphore_t, int);
82 extern_inline void sxe_semaphore_trigger_all(sxe_semaphore_t);
83 extern_inline void sxe_msemaphore_trigger_all(sxe_msemaphore_t, int);
84 extern_inline void sxe_semaphore_synchronise(sxe_semaphore_t);
85 extern_inline void sxe_msemaphore_synchronise(sxe_msemaphore_t, int);
86
87 /* thread-safe refcounter */
88 extern_inline void sxe_refcounter_init(sxe_refcounter_t);
89 extern_inline void sxe_refcounter_finish(sxe_refcounter_t);
90 extern_inline sxe_refcounter_t sxe_refcounter_new(void);
91 extern_inline void sxe_refcounter_free(sxe_refcounter_t);
92 extern_inline int sxe_refcounter_value(sxe_refcounter_t);
93 extern_inline int sxe_refcounter_incref(sxe_refcounter_t);
94 extern_inline int sxe_refcounter_decref(sxe_refcounter_t);
95
96 \f
97 extern_inline void
98 sxe_semaphore_init(sxe_semaphore_t sem)
99 {
100         sem->generation = 0;
101         pthread_mutex_init(&(sem->mtx), NULL);
102         pthread_cond_init(&(sem->cnd), NULL);
103 }
104 extern_inline void
105 sxe_msemaphore_init(sxe_msemaphore_t sem)
106 {
107         int i;
108         sem->generation = 0;
109         pthread_mutex_init(&(sem->mtx), NULL);
110         for (i = 0; i < SXE_MSEMAPH_MAX_CONDITIONS; i++)
111                 pthread_cond_init(&(sem->cnd[i]), NULL);
112 }
113 extern_inline void
114 sxe_semaphore_finish(sxe_semaphore_t sem)
115 {
116         pthread_mutex_lock(&(sem->mtx));
117         pthread_mutex_unlock(&(sem->mtx));
118         pthread_cond_destroy(&(sem->cnd));
119         pthread_mutex_destroy(&(sem->mtx));
120 }
121 extern_inline void
122 sxe_msemaphore_finish(sxe_msemaphore_t sem)
123 {
124         int i;
125         pthread_mutex_lock(&(sem->mtx));
126         pthread_mutex_unlock(&(sem->mtx));
127         for (i = 0; i < SXE_MSEMAPH_MAX_CONDITIONS; i++)
128                 pthread_cond_destroy(&(sem->cnd[i]));
129         pthread_mutex_destroy(&(sem->mtx));
130 }
131
132 extern_inline void
133 sxe_semaphore_trigger(sxe_semaphore_t sem)
134 {
135         pthread_mutex_lock(&(sem->mtx));
136         sem->generation++;
137         pthread_cond_signal(&(sem->cnd));
138         pthread_mutex_unlock(&(sem->mtx));
139 }
140 extern_inline void
141 sxe_msemaphore_trigger(sxe_msemaphore_t sem, int idx)
142 {
143         pthread_mutex_lock(&(sem->mtx));
144         sem->generation++;
145         pthread_cond_signal(&(sem->cnd[idx]));
146         pthread_mutex_unlock(&(sem->mtx));
147 }
148
149 extern_inline void
150 sxe_semaphore_trigger_all(sxe_semaphore_t sem)
151 {
152         pthread_mutex_lock(&(sem->mtx));
153         sem->generation++;
154         pthread_cond_broadcast(&(sem->cnd));
155         pthread_mutex_unlock(&(sem->mtx));
156 }
157 extern_inline void
158 sxe_msemaphore_trigger_all(sxe_msemaphore_t sem, int idx)
159 {
160         pthread_mutex_lock(&(sem->mtx));
161         sem->generation++;
162         pthread_cond_broadcast(&(sem->cnd[idx]));
163         pthread_mutex_unlock(&(sem->mtx));
164 }
165
166 extern_inline void
167 sxe_semaphore_synchronise(sxe_semaphore_t sem)
168 {
169         int generation;
170
171         pthread_mutex_lock(&(sem->mtx));
172         generation = sem->generation;
173         do {
174                 pthread_cond_wait(&(sem->cnd), &(sem->mtx));
175         } while(sem->generation == generation);
176         pthread_mutex_unlock(&(sem->mtx));
177 }
178 extern_inline void
179 sxe_msemaphore_synchronise(sxe_msemaphore_t sem, int idx)
180 {
181         int generation;
182
183         pthread_mutex_lock(&(sem->mtx));
184         generation = sem->generation;
185         do {
186                 pthread_cond_wait(&(sem->cnd[idx]), &(sem->mtx));
187         } while(sem->generation == generation);
188         pthread_mutex_unlock(&(sem->mtx));
189 }
190
191 #define SXE_SEMAPH_INIT(_sem)   sxe_semaphore_init(_sem)
192 #define SXE_MSEMAPH_INIT(_sem)  sxe_msemaphore_init(_sem)
193 #define SXE_SEMAPH_FINI(_sem)   sxe_semaphore_finish(_sem)
194 #define SXE_MSEMAPH_FINI(_sem)  sxe_msemaphore_finish(_sem)
195
196 #define SXE_SEMAPH_LOCK(_sem)                           \
197         pthread_mutex_lock(&SXE_SEMAPH_MUTEX(_sem));
198
199 #define SXE_SEMAPH_UNLOCK(_sem)                         \
200         pthread_mutex_unlock(&SXE_SEMAPH_MUTEX(_sem));
201
202 #define SXE_SEMAPH_SIGNAL(_sem)                         \
203         pthread_cond_signal(&SXE_SEMAPH_COND(_sem));
204
205 #define SXE_SEMAPH_BROADCAST(_sem)                      \
206         pthread_cond_broadcast(&SXE_SEMAPH_COND(_sem));
207
208 #define SXE_SEMAPH_WAIT(_sem)                   \
209         pthread_cond_wait(&SXE_SEMAPH_COND(_sem), &SXE_SEMAPH_MUTEX(_sem));
210
211 #define SXE_MSEMAPH_LOCK(_sem)                          \
212         pthread_mutex_lock(&SXE_MSEMAPH_MUTEX(_sem));
213
214 #define SXE_MSEMAPH_UNLOCK(_sem)                                \
215         pthread_mutex_unlock(&SXE_MSEMAPH_MUTEX(_sem));
216
217 #define SXE_MSEMAPH_SIGNAL(_sem, _idx)                          \
218         pthread_cond_signal(&SXE_MSEMAPH_COND(_sem, _idx));
219
220 #define SXE_MSEMAPH_BROADCAST(_sem, _idx)                       \
221         pthread_cond_broadcast(&SXE_SEMAPH_COND(_sem, _idx));
222
223 #define SXE_MSEMAPH_WAIT(_sem, _idx)                                    \
224         pthread_cond_wait(&SXE_MSEMAPH_COND(_sem, _idx),                \
225                           &SXE_MSEMAPH_MUTEX(_sem));
226
227 #define SXE_SEMAPH_TRIGGER(_sem)        sxe_semaphore_trigger(_sem)
228 #define SXE_MSEMAPH_TRIGGER(_sem, _idx) sxe_msemaphore_trigger(_sem, _idx)
229 #define SXE_SEMAPH_TRIGGER_ALL(_sem)    sxe_semaphore_trigger_all(_sem)
230 #define SXE_MSEMAPH_TRIGGER_ALL(_sem, _idx)     \
231         sxe_msemaphore_trigger_all(_sem, _idx)
232 #define SXE_SEMAPH_SYNCH(_sem)          sxe_semaphore_synchronise(_sem);
233 #define SXE_MSEMAPH_SYNCH(_sem, _idx)   sxe_msemaphore_synchronise(_sem, _idx);
234
235 #define WITH_SXE_SEMAPH_SYNCH(_sem, args...)                    \
236 do {                                                            \
237         pthread_mutex_lock(&SXE_SEMAPH_MUTEX(_sem));            \
238         args;                                                   \
239         pthread_cond_wait(&SXE_SEMAPH_COND(_sem),               \
240                           &SXE_SEMAPH_MUTEX(_sem));             \
241         pthread_mutex_unlock(&SXE_SEMAPH_MUTEX(_sem));          \
242 } while (0)
243
244 #define WITH_SXE_MSEMAPH_SYNCH(_sem, _idx, args...)             \
245 do {                                                            \
246         pthread_mutex_lock(&SXE_MSEMAPH_MUTEX(_sem));           \
247         args;                                                   \
248         pthread_cond_wait(&SXE_MSEMAPH_COND(_sem, _idx),        \
249                           &SXE_MSEMAPH_MUTEX(_sem));            \
250         pthread_mutex_unlock(&SXE_MSEMAPH_MUTEX(_sem));         \
251 } while (0)
252
253
254 /* thread-safe refcounter */
255 extern_inline void
256 sxe_refcounter_init(sxe_refcounter_t rc)
257 {
258         pthread_mutex_init(&(rc->mtx), NULL);
259         pthread_mutex_lock(&(rc->mtx));
260         rc->refcnt = 0;
261         pthread_mutex_unlock(&(rc->mtx));
262 }
263 extern_inline void
264 sxe_refcounter_finish(sxe_refcounter_t rc)
265 {
266         pthread_mutex_lock(&(rc->mtx));
267         rc->refcnt = 0;
268         pthread_mutex_unlock(&(rc->mtx));
269         pthread_mutex_destroy(&(rc->mtx));
270 }
271 extern_inline sxe_refcounter_t
272 sxe_refcounter_new(void)
273 {
274         sxe_refcounter_t rc = xnew(struct sxe_refcounter_s);
275         sxe_refcounter_init(rc);
276         return rc;
277 }
278 extern_inline void
279 sxe_refcounter_free(sxe_refcounter_t rc)
280 {
281         sxe_refcounter_finish(rc);
282         xfree(rc);
283         return;
284 }
285 /* accessors */
286 extern_inline int
287 sxe_refcounter_value(sxe_refcounter_t rc)
288 {
289         int result;
290
291         pthread_mutex_lock(&(rc->mtx));
292         result = rc->refcnt;
293         pthread_mutex_unlock(&(rc->mtx));
294
295         return result;
296 }
297 extern_inline int
298 sxe_refcounter_incref(sxe_refcounter_t rc)
299 {
300         int result;
301
302         pthread_mutex_lock(&(rc->mtx));
303         result = ++rc->refcnt;
304         pthread_mutex_unlock(&(rc->mtx));
305
306         return result;
307 }
308 extern_inline int
309 sxe_refcounter_decref(sxe_refcounter_t rc)
310 {
311         int result;
312
313         pthread_mutex_lock(&(rc->mtx));
314         result = --rc->refcnt;
315         pthread_mutex_unlock(&(rc->mtx));
316
317         return result;
318 }
319
320 /* pthreads */
321 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
322 # define xthread_create         GC_pthread_create
323 # define xthread_join           GC_pthread_join
324 # define xthread_detach         GC_pthread_detach
325 #else  /* !BDWGC */
326 # define xthread_create         pthread_create
327 # define xthread_join           pthread_join
328 # define xthread_detach         pthread_detach
329 #endif  /* BDWGC */
330
331 #else  /* !HAVE_THREADS */
332
333 typedef void *sxe_semaphore_t;
334 #define sxe_mutex_t     void
335 #define sxe_thread_t    void
336
337 #define SXE_MUTEX_INIT(_mtx)
338 #define SXE_MUTEX_FINI(_mtx)
339 #define SXE_MUTEX_LOCK(_mtx)
340 #define SXE_MUTEX_UNLOCK(_mtx)
341
342 #endif
343 #endif  /* INCLUDED_semaphore_h */