2 * atomic.c: Workarounds for atomic operations for platforms that dont have
3 * really atomic asm functions in atomic.h
6 * Dick Porter (dick@ximian.com)
8 * (C) 2002 Ximian, Inc.
14 #include <mono/utils/atomic.h>
16 #if defined (WAPI_NO_ATOMIC_ASM) || defined (BROKEN_64BIT_ATOMICS_INTRINSIC)
20 static pthread_mutex_t spin = PTHREAD_MUTEX_INITIALIZER;
22 #define NEED_64BIT_CMPXCHG_FALLBACK
26 #ifdef WAPI_NO_ATOMIC_ASM
28 static mono_once_t spin_once=MONO_ONCE_INIT;
30 static void spin_init(void)
32 g_warning("Using non-atomic functions! Expect race conditions when using process-shared handles!");
35 gint32 InterlockedCompareExchange(volatile gint32 *dest, gint32 exch,
41 mono_once(&spin_once, spin_init);
43 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
45 ret = pthread_mutex_lock(&spin);
53 ret = pthread_mutex_unlock(&spin);
56 pthread_cleanup_pop (0);
61 gpointer InterlockedCompareExchangePointer(volatile gpointer *dest,
62 gpointer exch, gpointer comp)
67 mono_once(&spin_once, spin_init);
69 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
71 ret = pthread_mutex_lock(&spin);
79 ret = pthread_mutex_unlock(&spin);
82 pthread_cleanup_pop (0);
87 gint32 InterlockedAdd(volatile gint32 *dest, gint32 add)
92 mono_once(&spin_once, spin_init);
94 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
96 thr_ret = pthread_mutex_lock(&spin);
97 g_assert (thr_ret == 0);
102 thr_ret = pthread_mutex_unlock(&spin);
103 g_assert (thr_ret == 0);
105 pthread_cleanup_pop (0);
110 gint64 InterlockedAdd64(volatile gint64 *dest, gint64 add)
115 mono_once(&spin_once, spin_init);
117 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
119 thr_ret = pthread_mutex_lock(&spin);
120 g_assert (thr_ret == 0);
125 thr_ret = pthread_mutex_unlock(&spin);
126 g_assert (thr_ret == 0);
128 pthread_cleanup_pop (0);
133 gint32 InterlockedIncrement(volatile gint32 *dest)
138 mono_once(&spin_once, spin_init);
140 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
142 thr_ret = pthread_mutex_lock(&spin);
143 g_assert (thr_ret == 0);
148 thr_ret = pthread_mutex_unlock(&spin);
149 g_assert (thr_ret == 0);
151 pthread_cleanup_pop (0);
156 gint64 InterlockedIncrement64(volatile gint64 *dest)
161 mono_once(&spin_once, spin_init);
163 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
165 thr_ret = pthread_mutex_lock(&spin);
166 g_assert (thr_ret == 0);
171 thr_ret = pthread_mutex_unlock(&spin);
172 g_assert (thr_ret == 0);
174 pthread_cleanup_pop (0);
179 gint32 InterlockedDecrement(volatile gint32 *dest)
184 mono_once(&spin_once, spin_init);
186 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
188 thr_ret = pthread_mutex_lock(&spin);
189 g_assert (thr_ret == 0);
194 thr_ret = pthread_mutex_unlock(&spin);
195 g_assert (thr_ret == 0);
197 pthread_cleanup_pop (0);
202 gint64 InterlockedDecrement64(volatile gint64 *dest)
207 mono_once(&spin_once, spin_init);
209 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
211 thr_ret = pthread_mutex_lock(&spin);
212 g_assert (thr_ret == 0);
217 thr_ret = pthread_mutex_unlock(&spin);
218 g_assert (thr_ret == 0);
220 pthread_cleanup_pop (0);
225 gint32 InterlockedExchange(volatile gint32 *dest, gint32 exch)
230 mono_once(&spin_once, spin_init);
232 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
234 thr_ret = pthread_mutex_lock(&spin);
235 g_assert (thr_ret == 0);
240 thr_ret = pthread_mutex_unlock(&spin);
241 g_assert (thr_ret == 0);
243 pthread_cleanup_pop (0);
248 gint64 InterlockedExchange64(volatile gint64 *dest, gint64 exch)
253 mono_once(&spin_once, spin_init);
255 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
257 thr_ret = pthread_mutex_lock(&spin);
258 g_assert (thr_ret == 0);
263 thr_ret = pthread_mutex_unlock(&spin);
264 g_assert (thr_ret == 0);
266 pthread_cleanup_pop (0);
271 gpointer InterlockedExchangePointer(volatile gpointer *dest, gpointer exch)
276 mono_once(&spin_once, spin_init);
278 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
280 thr_ret = pthread_mutex_lock(&spin);
281 g_assert (thr_ret == 0);
286 thr_ret = pthread_mutex_unlock(&spin);
287 g_assert (thr_ret == 0);
289 pthread_cleanup_pop (0);
294 gint32 InterlockedExchangeAdd(volatile gint32 *dest, gint32 add)
299 mono_once(&spin_once, spin_init);
301 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
303 thr_ret = pthread_mutex_lock(&spin);
304 g_assert (thr_ret == 0);
309 thr_ret = pthread_mutex_unlock(&spin);
310 g_assert (thr_ret == 0);
312 pthread_cleanup_pop (0);
317 gint64 InterlockedExchangeAdd64(volatile gint64 *dest, gint64 add)
322 mono_once(&spin_once, spin_init);
324 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
326 thr_ret = pthread_mutex_lock(&spin);
327 g_assert (thr_ret == 0);
332 thr_ret = pthread_mutex_unlock(&spin);
333 g_assert (thr_ret == 0);
335 pthread_cleanup_pop (0);
340 gint8 InterlockedRead8(volatile gint8 *src)
345 mono_once(&spin_once, spin_init);
347 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
349 thr_ret = pthread_mutex_lock(&spin);
350 g_assert (thr_ret == 0);
354 thr_ret = pthread_mutex_unlock(&spin);
355 g_assert (thr_ret == 0);
357 pthread_cleanup_pop (0);
362 gint16 InterlockedRead16(volatile gint16 *src)
367 mono_once(&spin_once, spin_init);
369 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
371 thr_ret = pthread_mutex_lock(&spin);
372 g_assert (thr_ret == 0);
376 thr_ret = pthread_mutex_unlock(&spin);
377 g_assert (thr_ret == 0);
379 pthread_cleanup_pop (0);
384 gint32 InterlockedRead(volatile gint32 *src)
389 mono_once(&spin_once, spin_init);
391 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
393 thr_ret = pthread_mutex_lock(&spin);
394 g_assert (thr_ret == 0);
398 thr_ret = pthread_mutex_unlock(&spin);
399 g_assert (thr_ret == 0);
401 pthread_cleanup_pop (0);
406 gint64 InterlockedRead64(volatile gint64 *src)
411 mono_once(&spin_once, spin_init);
413 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
415 thr_ret = pthread_mutex_lock(&spin);
416 g_assert (thr_ret == 0);
420 thr_ret = pthread_mutex_unlock(&spin);
421 g_assert (thr_ret == 0);
423 pthread_cleanup_pop (0);
428 gpointer InterlockedReadPointer(volatile gpointer *src)
433 mono_once(&spin_once, spin_init);
435 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
437 thr_ret = pthread_mutex_lock(&spin);
438 g_assert (thr_ret == 0);
442 thr_ret = pthread_mutex_unlock(&spin);
443 g_assert (thr_ret == 0);
445 pthread_cleanup_pop (0);
450 void InterlockedWrite(volatile gint8 *dst, gint8 val)
454 mono_once(&spin_once, spin_init);
456 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
458 thr_ret = pthread_mutex_lock(&spin);
459 g_assert (thr_ret == 0);
463 thr_ret = pthread_mutex_unlock(&spin);
464 g_assert (thr_ret == 0);
466 pthread_cleanup_pop (0);
469 void InterlockedWrite16(volatile gint16 *dst, gint16 val)
473 mono_once(&spin_once, spin_init);
475 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
477 thr_ret = pthread_mutex_lock(&spin);
478 g_assert (thr_ret == 0);
482 thr_ret = pthread_mutex_unlock(&spin);
483 g_assert (thr_ret == 0);
485 pthread_cleanup_pop (0);
488 void InterlockedWrite(volatile gint32 *dst, gint32 val)
492 mono_once(&spin_once, spin_init);
494 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
496 thr_ret = pthread_mutex_lock(&spin);
497 g_assert (thr_ret == 0);
501 thr_ret = pthread_mutex_unlock(&spin);
502 g_assert (thr_ret == 0);
504 pthread_cleanup_pop (0);
507 void InterlockedWrite64(volatile gint64 *dst, gint64 val)
511 mono_once(&spin_once, spin_init);
513 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
515 thr_ret = pthread_mutex_lock(&spin);
516 g_assert (thr_ret == 0);
520 thr_ret = pthread_mutex_unlock(&spin);
521 g_assert (thr_ret == 0);
523 pthread_cleanup_pop (0);
526 void InterlockedWritePointer(volatile gpointer *dst, gpointer val)
530 mono_once(&spin_once, spin_init);
532 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
534 thr_ret = pthread_mutex_lock(&spin);
535 g_assert (thr_ret == 0);
539 thr_ret = pthread_mutex_unlock(&spin);
540 g_assert (thr_ret == 0);
542 pthread_cleanup_pop (0);
547 #if defined (NEED_64BIT_CMPXCHG_FALLBACK)
549 #if defined (TARGET_OSX)
551 /* The compiler breaks if this code is in the header... */
554 InterlockedCompareExchange64(volatile gint64 *dest, gint64 exch, gint64 comp)
556 return __sync_val_compare_and_swap (dest, comp, exch);
559 #elif defined (HAVE_64BIT_CMPXCHG_FALLBACK)
561 #ifdef ENABLE_EXTENSION_MODULE
562 #include "../../../mono-extensions/mono/utils/atomic.c"
568 InterlockedCompareExchange64(volatile gint64 *dest, gint64 exch, gint64 comp)
572 pthread_mutex_lock (&spin);
578 pthread_mutex_unlock (&spin);