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 {
57 struct sxe_msemaphore_s {
59 pthread_cond_t cnd[SXE_MSEMAPH_MAX_CONDITIONS];
63 /* a thread-safe reference counter */
64 struct sxe_refcounter_s {
69 #define SXE_SEMAPH_MUTEX(_sem) ((_sem)->mtx)
70 #define SXE_SEMAPH_COND(_sem) ((_sem)->cnd)
71 #define SXE_MSEMAPH_MUTEX(_sem) ((_sem)->mtx)
72 #define SXE_MSEMAPH_COND(_sem, _idx) ((_sem)->cnd[(_idx)])
74 extern_inline void sxe_semaphore_init(sxe_semaphore_t);
75 extern_inline void sxe_msemaphore_init(sxe_msemaphore_t);
76 extern_inline void sxe_semaphore_finish(sxe_semaphore_t);
77 extern_inline void sxe_msemaphore_finish(sxe_msemaphore_t);
78 extern_inline void sxe_semaphore_trigger(sxe_semaphore_t);
79 extern_inline void sxe_msemaphore_trigger(sxe_msemaphore_t, int);
80 extern_inline void sxe_semaphore_trigger_all(sxe_semaphore_t);
81 extern_inline void sxe_msemaphore_trigger_all(sxe_msemaphore_t, int);
82 extern_inline void sxe_semaphore_synchronise(sxe_semaphore_t);
83 extern_inline void sxe_msemaphore_synchronise(sxe_msemaphore_t, int);
85 /* thread-safe refcounter */
86 extern_inline void sxe_refcounter_init(sxe_refcounter_t);
87 extern_inline void sxe_refcounter_finish(sxe_refcounter_t);
88 extern_inline sxe_refcounter_t sxe_refcounter_new(void);
89 extern_inline void sxe_refcounter_free(sxe_refcounter_t);
90 extern_inline int sxe_refcounter_value(sxe_refcounter_t);
91 extern_inline int sxe_refcounter_incref(sxe_refcounter_t);
92 extern_inline int sxe_refcounter_decref(sxe_refcounter_t);
96 sxe_semaphore_init(sxe_semaphore_t sem)
98 pthread_mutex_init(&(sem->mtx), NULL);
99 pthread_cond_init(&(sem->cnd), NULL);
102 sxe_msemaphore_init(sxe_msemaphore_t sem)
105 pthread_mutex_init(&(sem->mtx), NULL);
106 for (i = 0; i < SXE_MSEMAPH_MAX_CONDITIONS; i++)
107 pthread_cond_init(&(sem->cnd[i]), NULL);
110 sxe_semaphore_finish(sxe_semaphore_t sem)
112 pthread_mutex_lock(&(sem->mtx));
113 pthread_mutex_unlock(&(sem->mtx));
114 pthread_cond_destroy(&(sem->cnd));
115 pthread_mutex_destroy(&(sem->mtx));
118 sxe_msemaphore_finish(sxe_msemaphore_t sem)
121 pthread_mutex_lock(&(sem->mtx));
122 pthread_mutex_unlock(&(sem->mtx));
123 for (i = 0; i < SXE_MSEMAPH_MAX_CONDITIONS; i++)
124 pthread_cond_destroy(&(sem->cnd[i]));
125 pthread_mutex_destroy(&(sem->mtx));
129 sxe_semaphore_trigger(sxe_semaphore_t sem)
131 pthread_mutex_lock(&(sem->mtx));
132 pthread_cond_signal(&(sem->cnd));
133 pthread_mutex_unlock(&(sem->mtx));
136 sxe_msemaphore_trigger(sxe_msemaphore_t sem, int idx)
138 pthread_mutex_lock(&(sem->mtx));
139 pthread_cond_signal(&(sem->cnd[idx]));
140 pthread_mutex_unlock(&(sem->mtx));
144 sxe_semaphore_trigger_all(sxe_semaphore_t sem)
146 pthread_mutex_lock(&(sem->mtx));
147 pthread_cond_broadcast(&(sem->cnd));
148 pthread_mutex_unlock(&(sem->mtx));
151 sxe_msemaphore_trigger_all(sxe_msemaphore_t sem, int idx)
153 pthread_mutex_lock(&(sem->mtx));
154 pthread_cond_broadcast(&(sem->cnd[idx]));
155 pthread_mutex_unlock(&(sem->mtx));
159 sxe_semaphore_synchronise(sxe_semaphore_t sem)
161 pthread_mutex_lock(&(sem->mtx));
162 pthread_cond_wait(&(sem->cnd), &(sem->mtx));
163 pthread_mutex_unlock(&(sem->mtx));
166 sxe_msemaphore_synchronise(sxe_msemaphore_t sem, int idx)
168 pthread_mutex_lock(&(sem->mtx));
169 pthread_cond_wait(&(sem->cnd[idx]), &(sem->mtx));
170 pthread_mutex_unlock(&(sem->mtx));
173 #define SXE_SEMAPH_INIT(_sem) sxe_semaphore_init(_sem)
174 #define SXE_MSEMAPH_INIT(_sem) sxe_msemaphore_init(_sem)
175 #define SXE_SEMAPH_FINI(_sem) sxe_semaphore_finish(_sem)
176 #define SXE_MSEMAPH_FINI(_sem) sxe_msemaphore_finish(_sem)
178 #define SXE_SEMAPH_LOCK(_sem) \
179 pthread_mutex_lock(&SXE_SEMAPH_MUTEX(_sem));
181 #define SXE_SEMAPH_UNLOCK(_sem) \
182 pthread_mutex_unlock(&SXE_SEMAPH_MUTEX(_sem));
184 #define SXE_SEMAPH_SIGNAL(_sem) \
185 pthread_cond_signal(&SXE_SEMAPH_COND(_sem));
187 #define SXE_SEMAPH_BROADCAST(_sem) \
188 pthread_cond_broadcast(&SXE_SEMAPH_COND(_sem));
190 #define SXE_SEMAPH_WAIT(_sem) \
191 pthread_cond_wait(&SXE_SEMAPH_COND(_sem), &SXE_SEMAPH_MUTEX(_sem));
193 #define SXE_MSEMAPH_LOCK(_sem) \
194 pthread_mutex_lock(&SXE_MSEMAPH_MUTEX(_sem));
196 #define SXE_MSEMAPH_UNLOCK(_sem) \
197 pthread_mutex_unlock(&SXE_MSEMAPH_MUTEX(_sem));
199 #define SXE_MSEMAPH_SIGNAL(_sem, _idx) \
200 pthread_cond_signal(&SXE_MSEMAPH_COND(_sem, _idx));
202 #define SXE_MSEMAPH_BROADCAST(_sem, _idx) \
203 pthread_cond_broadcast(&SXE_SEMAPH_COND(_sem, _idx));
205 #define SXE_MSEMAPH_WAIT(_sem, _idx) \
206 pthread_cond_wait(&SXE_MSEMAPH_COND(_sem, _idx), \
207 &SXE_MSEMAPH_MUTEX(_sem));
209 #define SXE_SEMAPH_TRIGGER(_sem) sxe_semaphore_trigger(_sem)
210 #define SXE_MSEMAPH_TRIGGER(_sem, _idx) sxe_msemaphore_trigger(_sem, _idx)
211 #define SXE_SEMAPH_TRIGGER_ALL(_sem) sxe_semaphore_trigger_all(_sem)
212 #define SXE_MSEMAPH_TRIGGER_ALL(_sem, _idx) \
213 sxe_msemaphore_trigger_all(_sem, _idx)
214 #define SXE_SEMAPH_SYNCH(_sem) sxe_semaphore_synchronise(_sem);
215 #define SXE_MSEMAPH_SYNCH(_sem, _idx) sxe_msemaphore_synchronise(_sem, _idx);
217 #define WITH_SXE_SEMAPH_SYNCH(_sem, args...) \
219 pthread_mutex_lock(&SXE_SEMAPH_MUTEX(_sem)); \
221 pthread_cond_wait(&SXE_SEMAPH_COND(_sem), \
222 &SXE_SEMAPH_MUTEX(_sem)); \
223 pthread_mutex_unlock(&SXE_SEMAPH_MUTEX(_sem)); \
226 #define WITH_SXE_MSEMAPH_SYNCH(_sem, _idx, args...) \
228 pthread_mutex_lock(&SXE_MSEMAPH_MUTEX(_sem)); \
230 pthread_cond_wait(&SXE_MSEMAPH_COND(_sem, _idx), \
231 &SXE_MSEMAPH_MUTEX(_sem)); \
232 pthread_mutex_unlock(&SXE_MSEMAPH_MUTEX(_sem)); \
236 /* thread-safe refcounter */
238 sxe_refcounter_init(sxe_refcounter_t rc)
240 pthread_mutex_init(&(rc->mtx), NULL);
244 sxe_refcounter_finish(sxe_refcounter_t rc)
246 pthread_mutex_lock(&(rc->mtx));
247 pthread_mutex_unlock(&(rc->mtx));
248 pthread_mutex_destroy(&(rc->mtx));
251 extern_inline sxe_refcounter_t
252 sxe_refcounter_new(void)
254 sxe_refcounter_t rc = xnew(struct sxe_refcounter_s);
255 sxe_refcounter_init(rc);
259 sxe_refcounter_free(sxe_refcounter_t rc)
261 sxe_refcounter_finish(rc);
267 sxe_refcounter_value(sxe_refcounter_t rc)
271 pthread_mutex_lock(&(rc->mtx));
273 pthread_mutex_unlock(&(rc->mtx));
278 sxe_refcounter_incref(sxe_refcounter_t rc)
282 pthread_mutex_lock(&(rc->mtx));
283 result = ++rc->refcnt;
284 pthread_mutex_unlock(&(rc->mtx));
289 sxe_refcounter_decref(sxe_refcounter_t rc)
293 pthread_mutex_lock(&(rc->mtx));
294 result = --rc->refcnt;
295 pthread_mutex_unlock(&(rc->mtx));
301 #if defined HAVE_BDWGC && defined EF_USE_BDWGC
302 # define xthread_create GC_pthread_create
303 # define xthread_join GC_pthread_join
304 # define xthread_detach GC_pthread_detach
306 # define xthread_create pthread_create
307 # define xthread_join pthread_join
308 # define xthread_detach pthread_detach
311 #else /* !HAVE_THREADS */
313 typedef void *sxe_semaphore_t;
314 #define sxe_mutex_t void
315 #define sxe_thread_t void
317 #define SXE_MUTEX_INIT(_mtx)
318 #define SXE_MUTEX_FINI(_mtx)
319 #define SXE_MUTEX_LOCK(_mtx)
320 #define SXE_MUTEX_UNLOCK(_mtx)
323 #endif /* INCLUDED_semaphore_h */