Merge pull request #1617 from keneanung/OdbcCommandExceptionOnNoData
[mono.git] / mono / metadata / mono-wsq.c
index 1a110ec3a156979530612b23c326796dcc8ad35b..859fb69c55bf16d3e46548a37aeba73973c843e8 100644 (file)
@@ -5,6 +5,7 @@
  *   Gonzalo Paniagua Javier (gonzalo@novell.com)
  *
  * Copyright (c) 2010 Novell, Inc (http://www.novell.com)
+ * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
  */
 
 #include <string.h>
@@ -12,6 +13,7 @@
 #include <mono/metadata/mono-wsq.h>
 #include <mono/utils/mono-semaphore.h>
 #include <mono/utils/mono-tls.h>
+#include <mono/utils/atomic.h>
 
 #define INITIAL_LENGTH 32
 #define WSQ_DEBUG(...)
@@ -22,6 +24,7 @@ struct _MonoWSQ {
        volatile gint tail;
        MonoArray *queue;
        gint32 mask;
+       gint32 suspended;
        MonoSemType lock;
 };
 
@@ -59,6 +62,7 @@ mono_wsq_create ()
 
        wsq = g_new0 (MonoWSQ, 1);
        wsq->mask = INITIAL_LENGTH - 1;
+       wsq->suspended = 0;
        MONO_GC_REGISTER_ROOT_SINGLE (wsq->queue);
        root = mono_get_root_domain ();
        wsq->queue = mono_array_new_cached (root, mono_defaults.object_class, INITIAL_LENGTH);
@@ -70,6 +74,12 @@ mono_wsq_create ()
        return wsq;
 }
 
+gboolean
+mono_wsq_suspend (MonoWSQ *wsq)
+{
+       return InterlockedCompareExchange (&wsq->suspended, 1, 0) == 0;
+}
+
 void
 mono_wsq_destroy (MonoWSQ *wsq)
 {
@@ -110,6 +120,11 @@ mono_wsq_local_push (void *obj)
                return FALSE;
        }
 
+       if (wsq->suspended) {
+               WSQ_DEBUG ("local_push: wsq suspended\n");
+               return FALSE;
+       }
+
        tail = wsq->tail;
        if (tail < wsq->head + wsq->mask) {
                mono_array_setref (wsq->queue, tail & wsq->mask, (MonoObject *) obj);
@@ -131,7 +146,7 @@ mono_wsq_local_push (void *obj)
                for (i = 0; i < length; i++)
                        mono_array_setref (new_array, i, mono_array_get (wsq->queue, MonoObject*, (i + head) & wsq->mask));
 
-               mono_gc_bzero (mono_array_addr (wsq->queue, MonoObject *, 0), sizeof (MonoObject*) * length);
+               mono_gc_bzero_aligned (mono_array_addr (wsq->queue, MonoObject *, 0), sizeof (MonoObject*) * length);
                wsq->queue = new_array;
                wsq->head = 0;
                wsq->tail = tail = count;