2009-06-09 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / io-layer / atomic.c
index 1bf0bf416ac50522480329ae998a10fb72ce1639..07732fd8c1b22da790a69043dc368a7d571148c0 100644 (file)
 #include "mono/io-layer/wapi.h"
 
 #ifndef WAPI_ATOMIC_ASM
-#warning "Atomic functions are not atomic!"
 
-static pthread_mutex_t spin;
+static pthread_mutex_t spin = PTHREAD_MUTEX_INITIALIZER;
 static mono_once_t spin_once=MONO_ONCE_INIT;
 
 static void spin_init(void)
 {
-       pthread_mutex_init(&spin, 0);
-       g_warning("Using non-atomic functions!");
+       g_warning("Using non-atomic functions!  Expect race conditions when using process-shared handles!");
 }
 
 gint32 InterlockedCompareExchange(volatile gint32 *dest, gint32 exch,
                                  gint32 comp)
 {
        gint32 old;
+       int ret;
        
        mono_once(&spin_once, spin_init);
-       pthread_mutex_lock(&spin);
+       
+       pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+                             (void *)&spin);
+       ret = pthread_mutex_lock(&spin);
+       g_assert (ret == 0);
        
        old= *dest;
        if(old==comp) {
                *dest=exch;
        }
        
-       pthread_mutex_unlock(&spin);
+       ret = pthread_mutex_unlock(&spin);
+       g_assert (ret == 0);
+       
+       pthread_cleanup_pop (0);
 
        return(old);
 }
@@ -48,16 +54,24 @@ gpointer InterlockedCompareExchangePointer(volatile gpointer *dest,
                                           gpointer exch, gpointer comp)
 {
        gpointer old;
+       int ret;
        
        mono_once(&spin_once, spin_init);
-       pthread_mutex_lock(&spin);
+       
+       pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+                             (void *)&spin);
+       ret = pthread_mutex_lock(&spin);
+       g_assert (ret == 0);
        
        old= *dest;
        if(old==comp) {
                *dest=exch;
        }
        
-       pthread_mutex_unlock(&spin);
+       ret = pthread_mutex_unlock(&spin);
+       g_assert (ret == 0);
+       
+       pthread_cleanup_pop (0);
 
        return(old);
 }
@@ -65,14 +79,22 @@ gpointer InterlockedCompareExchangePointer(volatile gpointer *dest,
 gint32 InterlockedIncrement(volatile gint32 *dest)
 {
        gint32 ret;
+       int thr_ret;
        
        mono_once(&spin_once, spin_init);
-       pthread_mutex_lock(&spin);
        
-       *dest++;
+       pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+                             (void *)&spin);
+       thr_ret = pthread_mutex_lock(&spin);
+       g_assert (thr_ret == 0);
+
+       (*dest)++;
        ret= *dest;
        
-       pthread_mutex_unlock(&spin);
+       thr_ret = pthread_mutex_unlock(&spin);
+       g_assert (thr_ret == 0);
+       
+       pthread_cleanup_pop (0);
        
        return(ret);
 }
@@ -80,14 +102,22 @@ gint32 InterlockedIncrement(volatile gint32 *dest)
 gint32 InterlockedDecrement(volatile gint32 *dest)
 {
        gint32 ret;
+       int thr_ret;
        
        mono_once(&spin_once, spin_init);
-       pthread_mutex_lock(&spin);
        
-       *dest--;
+       pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+                             (void *)&spin);
+       thr_ret = pthread_mutex_lock(&spin);
+       g_assert (thr_ret == 0);
+       
+       (*dest)--;
        ret= *dest;
        
-       pthread_mutex_unlock(&spin);
+       thr_ret = pthread_mutex_unlock(&spin);
+       g_assert (thr_ret == 0);
+       
+       pthread_cleanup_pop (0);
        
        return(ret);
 }
@@ -95,14 +125,22 @@ gint32 InterlockedDecrement(volatile gint32 *dest)
 gint32 InterlockedExchange(volatile gint32 *dest, gint32 exch)
 {
        gint32 ret;
+       int thr_ret;
        
        mono_once(&spin_once, spin_init);
-       pthread_mutex_lock(&spin);
+       
+       pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+                             (void *)&spin);
+       thr_ret = pthread_mutex_lock(&spin);
+       g_assert (thr_ret == 0);
 
        ret=*dest;
        *dest=exch;
        
-       pthread_mutex_unlock(&spin);
+       thr_ret = pthread_mutex_unlock(&spin);
+       g_assert (thr_ret == 0);
+       
+       pthread_cleanup_pop (0);
        
        return(ret);
 }
@@ -110,14 +148,22 @@ gint32 InterlockedExchange(volatile gint32 *dest, gint32 exch)
 gpointer InterlockedExchangePointer(volatile gpointer *dest, gpointer exch)
 {
        gpointer ret;
+       int thr_ret;
        
        mono_once(&spin_once, spin_init);
-       pthread_mutex_lock(&spin);
+       
+       pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+                             (void *)&spin);
+       thr_ret = pthread_mutex_lock(&spin);
+       g_assert (thr_ret == 0);
        
        ret=*dest;
        *dest=exch;
        
-       pthread_mutex_unlock(&spin);
+       thr_ret = pthread_mutex_unlock(&spin);
+       g_assert (thr_ret == 0);
+       
+       pthread_cleanup_pop (0);
        
        return(ret);
 }
@@ -125,15 +171,23 @@ gpointer InterlockedExchangePointer(volatile gpointer *dest, gpointer exch)
 gint32 InterlockedExchangeAdd(volatile gint32 *dest, gint32 add)
 {
        gint32 ret;
+       int thr_ret;
        
        mono_once(&spin_once, spin_init);
-       pthread_mutex_lock(&spin);
+       
+       pthread_cleanup_push ((void(*)(void *))pthread_mutex_unlock,
+                             (void *)&spin);
+       thr_ret = pthread_mutex_lock(&spin);
+       g_assert (thr_ret == 0);
 
        ret= *dest;
        *dest+=add;
        
-       pthread_mutex_unlock(&spin);
-       
+       thr_ret = pthread_mutex_unlock(&spin);
+       g_assert (thr_ret == 0);
+
+       pthread_cleanup_pop (0);
+
        return(ret);
 }