[sgen] Only load an object's vtable word if absolutely necessary in M&S.
[mono.git] / mono / metadata / mono-wsq.c
index 83cc71589ccdcd43a295a11fd11bee51371c67b7..3c36dcee88da733f0dd0ba63276290a55127ed1d 100644 (file)
@@ -24,7 +24,8 @@ struct _MonoWSQ {
        MonoSemType lock;
 };
 
-static guint32 wsq_tlskey = -1;
+#define NO_KEY ((guint32) -1)
+static guint32 wsq_tlskey = NO_KEY;
 
 void
 mono_wsq_init ()
@@ -35,10 +36,10 @@ mono_wsq_init ()
 void
 mono_wsq_cleanup ()
 {
-       if (wsq_tlskey == -1)
+       if (wsq_tlskey == NO_KEY)
                return;
        TlsFree (wsq_tlskey);
-       wsq_tlskey = -1;
+       wsq_tlskey = NO_KEY;
 }
 
 MonoWSQ *
@@ -47,13 +48,19 @@ mono_wsq_create ()
        MonoWSQ *wsq;
        MonoDomain *root;
 
+       if (wsq_tlskey == NO_KEY)
+               return NULL;
+
        wsq = g_new0 (MonoWSQ, 1);
        wsq->mask = INITIAL_LENGTH - 1;
-       MONO_GC_REGISTER_ROOT (wsq->queue);
+       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);
        MONO_SEM_INIT (&wsq->lock, 1);
-       TlsSetValue (wsq_tlskey, wsq);
+       if (!TlsSetValue (wsq_tlskey, wsq)) {
+               mono_wsq_destroy (wsq);
+               wsq = NULL;
+       }
        return wsq;
 }
 
@@ -63,18 +70,20 @@ mono_wsq_destroy (MonoWSQ *wsq)
        if (wsq == NULL || wsq->queue == NULL)
                return;
 
-       /* TODO: clean up queue if not empty */
+       g_assert (mono_wsq_count (wsq) == 0);
        MONO_GC_UNREGISTER_ROOT (wsq->queue);
        MONO_SEM_DESTROY (&wsq->lock);
-       if (wsq_tlskey != -1 && TlsGetValue (wsq_tlskey) == wsq)
-               TlsSetValue (wsq_tlskey, NULL);
        memset (wsq, 0, sizeof (MonoWSQ));
+       if (wsq_tlskey != NO_KEY && TlsGetValue (wsq_tlskey) == wsq)
+               TlsSetValue (wsq_tlskey, NULL);
        g_free (wsq);
 }
 
 gint
 mono_wsq_count (MonoWSQ *wsq)
 {
+       if (!wsq)
+               return 0;
        return ((wsq->tail - wsq->head) & wsq->mask);
 }
 
@@ -86,7 +95,7 @@ mono_wsq_local_push (void *obj)
        int count;
        MonoWSQ *wsq;
 
-       if (obj == NULL)
+       if (obj == NULL || wsq_tlskey == NO_KEY)
                return FALSE;
 
        wsq = (MonoWSQ *) TlsGetValue (wsq_tlskey);
@@ -136,7 +145,7 @@ mono_wsq_local_pop (void **ptr)
        gboolean res;
        MonoWSQ *wsq;
 
-       if (ptr == NULL)
+       if (ptr == NULL || wsq_tlskey == NO_KEY)
                return FALSE;
 
        wsq = (MonoWSQ *) TlsGetValue (wsq_tlskey);
@@ -176,13 +185,13 @@ mono_wsq_local_pop (void **ptr)
 void
 mono_wsq_try_steal (MonoWSQ *wsq, void **ptr, guint32 ms_timeout)
 {
-       if (wsq == NULL || ptr == NULL || *ptr != NULL)
+       if (wsq == NULL || ptr == NULL || *ptr != NULL || wsq_tlskey == NO_KEY)
                return;
 
        if (TlsGetValue (wsq_tlskey) == wsq)
                return;
 
-       if (MONO_SEM_TIMEDWAIT (&wsq->lock, ms_timeout)) {
+       if (mono_sem_timedwait (&wsq->lock, ms_timeout, FALSE) == 0) {
                int head;
 
                head = wsq->head;