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>
15 #include <mono/utils/mono-mutex.h>
17 #if defined (WAPI_NO_ATOMIC_ASM) || defined (BROKEN_64BIT_ATOMICS_INTRINSIC)
21 static pthread_mutex_t spin G_GNUC_UNUSED = PTHREAD_MUTEX_INITIALIZER;
23 static mono_once_t spin_once G_GNUC_UNUSED = MONO_ONCE_INIT;
25 static void spin_init(void)
27 g_warning("Using non-atomic functions! Expect race conditions when using process-shared handles!");
30 #define NEED_64BIT_CMPXCHG_FALLBACK
34 #ifdef WAPI_NO_ATOMIC_ASM
36 gint32 InterlockedCompareExchange(volatile gint32 *dest, gint32 exch,
42 mono_once(&spin_once, spin_init);
44 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
46 ret = pthread_mutex_lock(&spin);
54 ret = pthread_mutex_unlock(&spin);
57 pthread_cleanup_pop (0);
62 gpointer InterlockedCompareExchangePointer(volatile gpointer *dest,
63 gpointer exch, gpointer comp)
68 mono_once(&spin_once, spin_init);
70 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
72 ret = pthread_mutex_lock(&spin);
80 ret = pthread_mutex_unlock(&spin);
83 pthread_cleanup_pop (0);
88 gint32 InterlockedAdd(volatile gint32 *dest, gint32 add)
93 mono_once(&spin_once, spin_init);
95 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
97 thr_ret = pthread_mutex_lock(&spin);
98 g_assert (thr_ret == 0);
103 thr_ret = pthread_mutex_unlock(&spin);
104 g_assert (thr_ret == 0);
106 pthread_cleanup_pop (0);
111 gint64 InterlockedAdd64(volatile gint64 *dest, gint64 add)
116 mono_once(&spin_once, spin_init);
118 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
120 thr_ret = pthread_mutex_lock(&spin);
121 g_assert (thr_ret == 0);
126 thr_ret = pthread_mutex_unlock(&spin);
127 g_assert (thr_ret == 0);
129 pthread_cleanup_pop (0);
134 gint32 InterlockedIncrement(volatile gint32 *dest)
139 mono_once(&spin_once, spin_init);
141 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
143 thr_ret = pthread_mutex_lock(&spin);
144 g_assert (thr_ret == 0);
149 thr_ret = pthread_mutex_unlock(&spin);
150 g_assert (thr_ret == 0);
152 pthread_cleanup_pop (0);
157 gint64 InterlockedIncrement64(volatile gint64 *dest)
162 mono_once(&spin_once, spin_init);
164 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
166 thr_ret = pthread_mutex_lock(&spin);
167 g_assert (thr_ret == 0);
172 thr_ret = pthread_mutex_unlock(&spin);
173 g_assert (thr_ret == 0);
175 pthread_cleanup_pop (0);
180 gint32 InterlockedDecrement(volatile gint32 *dest)
185 mono_once(&spin_once, spin_init);
187 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
189 thr_ret = pthread_mutex_lock(&spin);
190 g_assert (thr_ret == 0);
195 thr_ret = pthread_mutex_unlock(&spin);
196 g_assert (thr_ret == 0);
198 pthread_cleanup_pop (0);
203 gint64 InterlockedDecrement64(volatile gint64 *dest)
208 mono_once(&spin_once, spin_init);
210 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
212 thr_ret = pthread_mutex_lock(&spin);
213 g_assert (thr_ret == 0);
218 thr_ret = pthread_mutex_unlock(&spin);
219 g_assert (thr_ret == 0);
221 pthread_cleanup_pop (0);
226 gint32 InterlockedExchange(volatile gint32 *dest, gint32 exch)
231 mono_once(&spin_once, spin_init);
233 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
235 thr_ret = pthread_mutex_lock(&spin);
236 g_assert (thr_ret == 0);
241 thr_ret = pthread_mutex_unlock(&spin);
242 g_assert (thr_ret == 0);
244 pthread_cleanup_pop (0);
249 gint64 InterlockedExchange64(volatile gint64 *dest, gint64 exch)
254 mono_once(&spin_once, spin_init);
256 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
258 thr_ret = pthread_mutex_lock(&spin);
259 g_assert (thr_ret == 0);
264 thr_ret = pthread_mutex_unlock(&spin);
265 g_assert (thr_ret == 0);
267 pthread_cleanup_pop (0);
272 gpointer InterlockedExchangePointer(volatile gpointer *dest, gpointer exch)
277 mono_once(&spin_once, spin_init);
279 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
281 thr_ret = pthread_mutex_lock(&spin);
282 g_assert (thr_ret == 0);
287 thr_ret = pthread_mutex_unlock(&spin);
288 g_assert (thr_ret == 0);
290 pthread_cleanup_pop (0);
295 gint32 InterlockedExchangeAdd(volatile gint32 *dest, gint32 add)
300 mono_once(&spin_once, spin_init);
302 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
304 thr_ret = pthread_mutex_lock(&spin);
305 g_assert (thr_ret == 0);
310 thr_ret = pthread_mutex_unlock(&spin);
311 g_assert (thr_ret == 0);
313 pthread_cleanup_pop (0);
318 gint64 InterlockedExchangeAdd64(volatile gint64 *dest, gint64 add)
323 mono_once(&spin_once, spin_init);
325 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
327 thr_ret = pthread_mutex_lock(&spin);
328 g_assert (thr_ret == 0);
333 thr_ret = pthread_mutex_unlock(&spin);
334 g_assert (thr_ret == 0);
336 pthread_cleanup_pop (0);
341 gint8 InterlockedRead8(volatile gint8 *src)
346 mono_once(&spin_once, spin_init);
348 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
350 thr_ret = pthread_mutex_lock(&spin);
351 g_assert (thr_ret == 0);
355 thr_ret = pthread_mutex_unlock(&spin);
356 g_assert (thr_ret == 0);
358 pthread_cleanup_pop (0);
363 gint16 InterlockedRead16(volatile gint16 *src)
368 mono_once(&spin_once, spin_init);
370 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
372 thr_ret = pthread_mutex_lock(&spin);
373 g_assert (thr_ret == 0);
377 thr_ret = pthread_mutex_unlock(&spin);
378 g_assert (thr_ret == 0);
380 pthread_cleanup_pop (0);
385 gint32 InterlockedRead(volatile gint32 *src)
390 mono_once(&spin_once, spin_init);
392 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
394 thr_ret = pthread_mutex_lock(&spin);
395 g_assert (thr_ret == 0);
399 thr_ret = pthread_mutex_unlock(&spin);
400 g_assert (thr_ret == 0);
402 pthread_cleanup_pop (0);
407 gint64 InterlockedRead64(volatile gint64 *src)
412 mono_once(&spin_once, spin_init);
414 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
416 thr_ret = pthread_mutex_lock(&spin);
417 g_assert (thr_ret == 0);
421 thr_ret = pthread_mutex_unlock(&spin);
422 g_assert (thr_ret == 0);
424 pthread_cleanup_pop (0);
429 gpointer InterlockedReadPointer(volatile gpointer *src)
434 mono_once(&spin_once, spin_init);
436 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
438 thr_ret = pthread_mutex_lock(&spin);
439 g_assert (thr_ret == 0);
443 thr_ret = pthread_mutex_unlock(&spin);
444 g_assert (thr_ret == 0);
446 pthread_cleanup_pop (0);
451 void InterlockedWrite(volatile gint8 *dst, gint8 val)
455 mono_once(&spin_once, spin_init);
457 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
459 thr_ret = pthread_mutex_lock(&spin);
460 g_assert (thr_ret == 0);
464 thr_ret = pthread_mutex_unlock(&spin);
465 g_assert (thr_ret == 0);
467 pthread_cleanup_pop (0);
470 void InterlockedWrite16(volatile gint16 *dst, gint16 val)
474 mono_once(&spin_once, spin_init);
476 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
478 thr_ret = pthread_mutex_lock(&spin);
479 g_assert (thr_ret == 0);
483 thr_ret = pthread_mutex_unlock(&spin);
484 g_assert (thr_ret == 0);
486 pthread_cleanup_pop (0);
489 void InterlockedWrite(volatile gint32 *dst, gint32 val)
493 mono_once(&spin_once, spin_init);
495 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
497 thr_ret = pthread_mutex_lock(&spin);
498 g_assert (thr_ret == 0);
502 thr_ret = pthread_mutex_unlock(&spin);
503 g_assert (thr_ret == 0);
505 pthread_cleanup_pop (0);
508 void InterlockedWrite64(volatile gint64 *dst, gint64 val)
512 mono_once(&spin_once, spin_init);
514 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
516 thr_ret = pthread_mutex_lock(&spin);
517 g_assert (thr_ret == 0);
521 thr_ret = pthread_mutex_unlock(&spin);
522 g_assert (thr_ret == 0);
524 pthread_cleanup_pop (0);
527 void InterlockedWritePointer(volatile gpointer *dst, gpointer val)
531 mono_once(&spin_once, spin_init);
533 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
535 thr_ret = pthread_mutex_lock(&spin);
536 g_assert (thr_ret == 0);
540 thr_ret = pthread_mutex_unlock(&spin);
541 g_assert (thr_ret == 0);
543 pthread_cleanup_pop (0);
548 #if defined (NEED_64BIT_CMPXCHG_FALLBACK)
550 #if defined (TARGET_OSX)
552 /* The compiler breaks if this code is in the header... */
555 InterlockedCompareExchange64(volatile gint64 *dest, gint64 exch, gint64 comp)
557 return __sync_val_compare_and_swap (dest, comp, exch);
560 #elif defined (HAVE_64BIT_CMPXCHG_FALLBACK)
562 #ifdef ENABLE_EXTENSION_MODULE
563 #include "../../../mono-extensions/mono/utils/atomic.c"
569 InterlockedCompareExchange64(volatile gint64 *dest, gint64 exch, gint64 comp)
574 mono_once(&spin_once, spin_init);
576 pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
578 ret = pthread_mutex_lock(&spin);
586 ret = pthread_mutex_unlock(&spin);
589 pthread_cleanup_pop (0);