1 /* semaphore.h - declarations for multi-threaded code
3 Copyright (C) 2006 Sebastian Freundt
5 This file is part of SXEmacs
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.
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.
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/>. */
21 /* Synched up with: Not in FSF. */
23 #ifndef INCLUDED_semaphore_h_
24 #define INCLUDED_semaphore_h_
26 #if defined(HAVE_THREADS)
29 /* decouple ordinary pthread mtxes */
30 #define sxe_thread_t pthread_t
31 #define sxe_mutex_t pthread_mutex_t
33 typedef void*(*sxe_thread_f)(void*);
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)
40 #define WITH_SXE_MUTEX(_mtx, args...) \
41 SXE_MUTEX_LOCK(_mtx); \
43 SXE_MUTEX_UNLOCK(_mtx);
46 #define SXE_MSEMAPH_MAX_CONDITIONS 4
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;
52 struct sxe_semaphore_s {
58 struct sxe_msemaphore_s {
60 pthread_cond_t cnd[SXE_MSEMAPH_MAX_CONDITIONS];
65 /* a thread-safe reference counter */
66 struct sxe_refcounter_s {
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)])
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);
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);
98 sxe_semaphore_init(sxe_semaphore_t sem)
101 pthread_mutex_init(&(sem->mtx), NULL);
102 pthread_cond_init(&(sem->cnd), NULL);
105 sxe_msemaphore_init(sxe_msemaphore_t sem)
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);
114 sxe_semaphore_finish(sxe_semaphore_t sem)
116 pthread_mutex_lock(&(sem->mtx));
117 pthread_mutex_unlock(&(sem->mtx));
118 pthread_cond_destroy(&(sem->cnd));
119 pthread_mutex_destroy(&(sem->mtx));
122 sxe_msemaphore_finish(sxe_msemaphore_t sem)
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));
133 sxe_semaphore_trigger(sxe_semaphore_t sem)
135 pthread_mutex_lock(&(sem->mtx));
137 pthread_cond_signal(&(sem->cnd));
138 pthread_mutex_unlock(&(sem->mtx));
141 sxe_msemaphore_trigger(sxe_msemaphore_t sem, int idx)
143 pthread_mutex_lock(&(sem->mtx));
145 pthread_cond_signal(&(sem->cnd[idx]));
146 pthread_mutex_unlock(&(sem->mtx));
150 sxe_semaphore_trigger_all(sxe_semaphore_t sem)
152 pthread_mutex_lock(&(sem->mtx));
154 pthread_cond_broadcast(&(sem->cnd));
155 pthread_mutex_unlock(&(sem->mtx));
158 sxe_msemaphore_trigger_all(sxe_msemaphore_t sem, int idx)
160 pthread_mutex_lock(&(sem->mtx));
162 pthread_cond_broadcast(&(sem->cnd[idx]));
163 pthread_mutex_unlock(&(sem->mtx));
167 sxe_semaphore_synchronise(sxe_semaphore_t sem)
171 pthread_mutex_lock(&(sem->mtx));
172 generation = sem->generation;
174 pthread_cond_wait(&(sem->cnd), &(sem->mtx));
175 } while(sem->generation == generation);
176 pthread_mutex_unlock(&(sem->mtx));
179 sxe_msemaphore_synchronise(sxe_msemaphore_t sem, int idx)
183 pthread_mutex_lock(&(sem->mtx));
184 generation = sem->generation;
186 pthread_cond_wait(&(sem->cnd[idx]), &(sem->mtx));
187 } while(sem->generation == generation);
188 pthread_mutex_unlock(&(sem->mtx));
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)
196 #define SXE_SEMAPH_LOCK(_sem) \
197 pthread_mutex_lock(&SXE_SEMAPH_MUTEX(_sem));
199 #define SXE_SEMAPH_UNLOCK(_sem) \
200 pthread_mutex_unlock(&SXE_SEMAPH_MUTEX(_sem));
202 #define SXE_SEMAPH_SIGNAL(_sem) \
203 pthread_cond_signal(&SXE_SEMAPH_COND(_sem));
205 #define SXE_SEMAPH_BROADCAST(_sem) \
206 pthread_cond_broadcast(&SXE_SEMAPH_COND(_sem));
208 #define SXE_SEMAPH_WAIT(_sem) \
209 pthread_cond_wait(&SXE_SEMAPH_COND(_sem), &SXE_SEMAPH_MUTEX(_sem));
211 #define SXE_MSEMAPH_LOCK(_sem) \
212 pthread_mutex_lock(&SXE_MSEMAPH_MUTEX(_sem));
214 #define SXE_MSEMAPH_UNLOCK(_sem) \
215 pthread_mutex_unlock(&SXE_MSEMAPH_MUTEX(_sem));
217 #define SXE_MSEMAPH_SIGNAL(_sem, _idx) \
218 pthread_cond_signal(&SXE_MSEMAPH_COND(_sem, _idx));
220 #define SXE_MSEMAPH_BROADCAST(_sem, _idx) \
221 pthread_cond_broadcast(&SXE_SEMAPH_COND(_sem, _idx));
223 #define SXE_MSEMAPH_WAIT(_sem, _idx) \
224 pthread_cond_wait(&SXE_MSEMAPH_COND(_sem, _idx), \
225 &SXE_MSEMAPH_MUTEX(_sem));
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);
235 #define WITH_SXE_SEMAPH_SYNCH(_sem, args...) \
237 pthread_mutex_lock(&SXE_SEMAPH_MUTEX(_sem)); \
239 pthread_cond_wait(&SXE_SEMAPH_COND(_sem), \
240 &SXE_SEMAPH_MUTEX(_sem)); \
241 pthread_mutex_unlock(&SXE_SEMAPH_MUTEX(_sem)); \
244 #define WITH_SXE_MSEMAPH_SYNCH(_sem, _idx, args...) \
246 pthread_mutex_lock(&SXE_MSEMAPH_MUTEX(_sem)); \
248 pthread_cond_wait(&SXE_MSEMAPH_COND(_sem, _idx), \
249 &SXE_MSEMAPH_MUTEX(_sem)); \
250 pthread_mutex_unlock(&SXE_MSEMAPH_MUTEX(_sem)); \
254 /* thread-safe refcounter */
256 sxe_refcounter_init(sxe_refcounter_t rc)
258 pthread_mutex_init(&(rc->mtx), NULL);
259 pthread_mutex_lock(&(rc->mtx));
261 pthread_mutex_unlock(&(rc->mtx));
264 sxe_refcounter_finish(sxe_refcounter_t rc)
266 pthread_mutex_lock(&(rc->mtx));
268 pthread_mutex_unlock(&(rc->mtx));
269 pthread_mutex_destroy(&(rc->mtx));
271 extern_inline sxe_refcounter_t
272 sxe_refcounter_new(void)
274 sxe_refcounter_t rc = xnew(struct sxe_refcounter_s);
275 sxe_refcounter_init(rc);
279 sxe_refcounter_free(sxe_refcounter_t rc)
281 sxe_refcounter_finish(rc);
287 sxe_refcounter_value(sxe_refcounter_t rc)
291 pthread_mutex_lock(&(rc->mtx));
293 pthread_mutex_unlock(&(rc->mtx));
298 sxe_refcounter_incref(sxe_refcounter_t rc)
302 pthread_mutex_lock(&(rc->mtx));
303 result = ++rc->refcnt;
304 pthread_mutex_unlock(&(rc->mtx));
309 sxe_refcounter_decref(sxe_refcounter_t rc)
313 pthread_mutex_lock(&(rc->mtx));
314 result = --rc->refcnt;
315 pthread_mutex_unlock(&(rc->mtx));
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
326 # define xthread_create pthread_create
327 # define xthread_join pthread_join
328 # define xthread_detach pthread_detach
331 #else /* !HAVE_THREADS */
333 typedef void *sxe_semaphore_t;
334 #define sxe_mutex_t void
335 #define sxe_thread_t void
337 #define SXE_MUTEX_INIT(_mtx)
338 #define SXE_MUTEX_FINI(_mtx)
339 #define SXE_MUTEX_LOCK(_mtx)
340 #define SXE_MUTEX_UNLOCK(_mtx)
343 #endif /* INCLUDED_semaphore_h */