Fix warnings.
[mono.git] / mono / metadata / threads.c
index 120bedc008d6c4c470b03e66c0b6bceb93c10d79..660eabaf632d7c7fb9847dd59973f34cd6919f8d 100644 (file)
@@ -8,6 +8,7 @@
  *
  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
+ * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
  */
 
 #include <config.h>
@@ -44,6 +45,7 @@
 #include <mono/utils/mono-time.h>
 #include <mono/utils/mono-threads.h>
 #include <mono/utils/hazard-pointer.h>
+#include <mono/utils/mono-tls.h>
 
 #include <mono/metadata/gc-internal.h>
 
@@ -147,7 +149,7 @@ static MonoGHashTable *threads_starting_up = NULL;
 static MonoGHashTable *thread_start_args = NULL;
 
 /* The TLS key that holds the MonoObject assigned to each thread */
-static guint32 current_object_key = -1;
+static MonoNativeTlsKey current_object_key;
 
 #ifdef MONO_HAVE_FAST_TLS
 /* we need to use both the Tls* functions and __thread because
@@ -156,12 +158,12 @@ static guint32 current_object_key = -1;
 MONO_FAST_TLS_DECLARE(tls_current_object);
 #define SET_CURRENT_OBJECT(x) do { \
        MONO_FAST_TLS_SET (tls_current_object, x); \
-       TlsSetValue (current_object_key, x); \
+       mono_native_tls_set_value (current_object_key, x); \
 } while (FALSE)
 #define GET_CURRENT_OBJECT() ((MonoInternalThread*) MONO_FAST_TLS_GET (tls_current_object))
 #else
-#define SET_CURRENT_OBJECT(x) TlsSetValue (current_object_key, x)
-#define GET_CURRENT_OBJECT() (MonoInternalThread*) TlsGetValue (current_object_key)
+#define SET_CURRENT_OBJECT(x) mono_native_tls_set_value (current_object_key, x)
+#define GET_CURRENT_OBJECT() (MonoInternalThread*) mono_native_tls_get_value (current_object_key)
 #endif
 
 /* function called at thread start */
@@ -216,7 +218,7 @@ get_next_managed_thread_id (void)
        return InterlockedIncrement (&managed_thread_id_counter);
 }
 
-guint32
+MonoNativeTlsKey
 mono_thread_get_tls_key (void)
 {
        return current_object_key;
@@ -366,6 +368,8 @@ static void thread_cleanup (MonoInternalThread *thread)
        }
        mono_release_type_locks (thread);
 
+       ensure_synch_cs_set (thread);
+
        EnterCriticalSection (thread->synch_cs);
 
        thread->state |= ThreadState_Stopped;
@@ -647,7 +651,7 @@ gpointer mono_create_thread (WapiSecurityAttributes *security,
 #ifdef HOST_WIN32
        DWORD real_tid;
 
-       res = CreateThread (security, stacksize, start, param, create, &real_tid);
+       res = mono_threads_CreateThread (security, stacksize, start, param, create, &real_tid);
        if (tid)
                *tid = real_tid;
 #else
@@ -764,6 +768,9 @@ mono_thread_get_stack_bounds (guint8 **staddr, size_t *stsize)
 #if defined(HAVE_PTHREAD_GET_STACKSIZE_NP) && defined(HAVE_PTHREAD_GET_STACKADDR_NP)
        *staddr = (guint8*)pthread_get_stackaddr_np (pthread_self ());
        *stsize = pthread_get_stacksize_np (pthread_self ());
+
+       /* staddr points to the start of the stack, not the end */
+       *staddr -= *stsize;
        *staddr = (guint8*)((gssize)*staddr & ~(mono_pagesize () - 1));
        return;
        /* FIXME: simplify the mess below */
@@ -1973,21 +1980,18 @@ ves_icall_System_Threading_Thread_GetState (MonoInternalThread* this)
 
 void ves_icall_System_Threading_Thread_Interrupt_internal (MonoInternalThread *this)
 {
-       gboolean throw = FALSE;
-       
+       MonoInternalThread *current;
+       gboolean throw;
+
        ensure_synch_cs_set (this);
 
-       if (this == mono_thread_internal_current ())
-               return;
-       
-       EnterCriticalSection (this->synch_cs);
-       
-       this->thread_interrupt_requested = TRUE;
-       
-       if (this->state & ThreadState_WaitSleepJoin) {
-               throw = TRUE;
-       }
-       
+       current = mono_thread_internal_current ();
+
+       EnterCriticalSection (this->synch_cs);  
+
+       this->thread_interrupt_requested = TRUE;        
+       throw = current != this && (this->state & ThreadState_WaitSleepJoin);   
+
        LeaveCriticalSection (this->synch_cs);
        
        if (throw) {
@@ -2381,6 +2385,18 @@ ves_icall_System_Threading_Thread_VolatileReadIntPtr (void *ptr)
        return (void *)  *((volatile void **) ptr);
 }
 
+double
+ves_icall_System_Threading_Thread_VolatileReadDouble (void *ptr)
+{
+       return *((volatile double *) (ptr));
+}
+
+float
+ves_icall_System_Threading_Thread_VolatileReadFloat (void *ptr)
+{
+       return *((volatile float *) (ptr));
+}
+
 void
 ves_icall_System_Threading_Thread_VolatileWrite1 (void *ptr, gint8 value)
 {
@@ -2417,6 +2433,18 @@ ves_icall_System_Threading_Thread_VolatileWriteObject (void *ptr, void *value)
        mono_gc_wbarrier_generic_store (ptr, value);
 }
 
+void
+ves_icall_System_Threading_Thread_VolatileWriteDouble (void *ptr, double value)
+{
+       *((volatile double *) ptr) = value;
+}
+
+void
+ves_icall_System_Threading_Thread_VolatileWriteFloat (void *ptr, float value)
+{
+       *((volatile float *) ptr) = value;
+}
+
 void mono_thread_init (MonoThreadStartCB start_cb,
                       MonoThreadAttachCB attach_cb)
 {
@@ -2431,7 +2459,7 @@ void mono_thread_init (MonoThreadStartCB start_cb,
        mono_init_static_data_info (&context_static_info);
 
        MONO_FAST_TLS_INIT (tls_current_object);
-       current_object_key=TlsAlloc();
+       mono_native_tls_alloc (&current_object_key, NULL);
        THREAD_DEBUG (g_message ("%s: Allocated current_object_key %d", __func__, current_object_key));
 
        mono_thread_start_cb = start_cb;
@@ -2474,7 +2502,7 @@ void mono_thread_cleanup (void)
        CloseHandle (background_change_event);
 #endif
 
-       TlsFree (current_object_key);
+       mono_native_tls_free (current_object_key);
 }
 
 void
@@ -4289,26 +4317,27 @@ mono_thread_test_state (MonoInternalThread *thread, MonoThreadState test)
        return ret;
 }
 
-static MonoClassField *execution_context_field;
+//static MonoClassField *execution_context_field;
 
 static MonoObject**
 get_execution_context_addr (void)
 {
        MonoDomain *domain = mono_domain_get ();
-       guint32 offset;
+       guint32 offset = domain->execution_context_field_offset;
 
-       if (!execution_context_field) {
-               execution_context_field = mono_class_get_field_from_name (mono_defaults.thread_class,
-                               "_ec");
-               g_assert (execution_context_field);
-       }
+       if (!offset) {
+               MonoClassField *field = mono_class_get_field_from_name (mono_defaults.thread_class, "_ec");
+               g_assert (field);
 
-       g_assert (mono_class_try_get_vtable (domain, mono_defaults.appdomain_class));
+               g_assert (mono_class_try_get_vtable (domain, mono_defaults.appdomain_class));
 
-       mono_domain_lock (domain);
-       offset = GPOINTER_TO_UINT (g_hash_table_lookup (domain->special_static_fields, execution_context_field));
-       mono_domain_unlock (domain);
-       g_assert (offset);
+               mono_domain_lock (domain);
+               offset = GPOINTER_TO_UINT (g_hash_table_lookup (domain->special_static_fields, field));
+               mono_domain_unlock (domain);
+               g_assert (offset);
+
+               domain->execution_context_field_offset = offset;
+       }
 
        return (MonoObject**) mono_get_special_static_data (offset);
 }
@@ -4460,6 +4489,7 @@ abort_thread_internal (MonoInternalThread *thread, gboolean can_raise_exception,
                        mono_thread_info_setup_async_call (info, self_interrupt_thread, NULL);
                mono_thread_info_resume (mono_thread_info_get_tid (info));
        } else {
+               gpointer interrupt_handle;
                /* 
                 * This will cause waits to be broken.
                 * It will also prevent the thread from entering a wait, so if the thread returns
@@ -4468,9 +4498,12 @@ abort_thread_internal (MonoInternalThread *thread, gboolean can_raise_exception,
                 * make it return.
                 */
                InterlockedIncrement (&thread_interruption_requested);
+#ifndef HOST_WIN32
+               interrupt_handle = wapi_prepare_interrupt_thread (thread->handle);
+#endif
                mono_thread_info_resume (mono_thread_info_get_tid (info));
 #ifndef HOST_WIN32
-               wapi_interrupt_thread (thread->handle);
+               wapi_finish_interrupt_thread (interrupt_handle);
 #endif
        }
        /*FIXME we need to wait for interruption to complete -- figure out how much into interruption we should wait for here*/
@@ -4511,13 +4544,19 @@ suspend_thread_internal (MonoInternalThread *thread, gboolean interrupt)
                if (running_managed && !protected_wrapper) {
                        transition_to_suspended (thread);
                } else {
+                       gpointer interrupt_handle;
+
                        if (InterlockedCompareExchange (&thread->interruption_requested, 1, 0) == 0)
                                InterlockedIncrement (&thread_interruption_requested);
 #ifndef HOST_WIN32
                        if (interrupt)
-                               wapi_interrupt_thread (thread->handle);
+                               interrupt_handle = wapi_prepare_interrupt_thread (thread->handle);
 #endif
                        mono_thread_info_resume (mono_thread_info_get_tid (info));
+#ifndef HOST_WIN32
+                       if (interrupt)
+                               wapi_finish_interrupt_thread (interrupt_handle);
+#endif
                        LeaveCriticalSection (thread->synch_cs);
                }
        }