summaryrefslogtreecommitdiff
path: root/mono/metadata/threads.c
diff options
context:
space:
mode:
Diffstat (limited to 'mono/metadata/threads.c')
-rwxr-xr-xmono/metadata/threads.c1038
1 files changed, 523 insertions, 515 deletions
diff --git a/mono/metadata/threads.c b/mono/metadata/threads.c
index a8720ba5bf..1b421c4a69 100755
--- a/mono/metadata/threads.c
+++ b/mono/metadata/threads.c
@@ -48,6 +48,7 @@
#include <mono/utils/hazard-pointer.h>
#include <mono/utils/mono-tls.h>
#include <mono/utils/atomic.h>
+#include <mono/utils/mono-memory-model.h>
#include <mono/metadata/gc-internal.h>
@@ -77,6 +78,9 @@ size_t pthread_get_stacksize_np(pthread_t);
#define SPIN_UNLOCK(i) i = 0
+#define LOCK_THREAD(thread) lock_thread((thread))
+#define UNLOCK_THREAD(thread) unlock_thread((thread))
+
/* Provide this for systems with glib < 2.6 */
#ifndef G_GSIZE_FORMAT
# if GLIB_SIZEOF_LONG == 8
@@ -86,13 +90,13 @@ size_t pthread_get_stacksize_np(pthread_t);
# endif
#endif
-struct StartInfo
+typedef struct
{
guint32 (*func)(void *);
MonoThread *obj;
MonoObject *delegate;
void *start_arg;
-};
+} StartInfo;
typedef union {
gint32 ival;
@@ -194,7 +198,6 @@ static void mono_free_static_data (gpointer* static_data, gboolean threadlocal);
static void mono_init_static_data_info (StaticDataInfo *static_data);
static guint32 mono_alloc_static_data_slot (StaticDataInfo *static_data, guint32 size, guint32 align);
static gboolean mono_thread_resume (MonoInternalThread* thread);
-static void mono_thread_start (MonoThread *thread);
static void signal_thread_state_change (MonoInternalThread *thread);
static void abort_thread_internal (MonoInternalThread *thread, gboolean can_raise_exception, gboolean install_async_abort);
static void suspend_thread_internal (MonoInternalThread *thread, gboolean interrupt);
@@ -323,14 +326,14 @@ static gboolean handle_remove(MonoInternalThread *thread)
static void ensure_synch_cs_set (MonoInternalThread *thread)
{
CRITICAL_SECTION *synch_cs;
-
+
if (thread->synch_cs != NULL) {
return;
}
-
+
synch_cs = g_new0 (CRITICAL_SECTION, 1);
InitializeCriticalSection (synch_cs);
-
+
if (InterlockedCompareExchangePointer ((gpointer *)&thread->synch_cs,
synch_cs, NULL) != NULL) {
/* Another thread must have installed this CS */
@@ -339,6 +342,22 @@ static void ensure_synch_cs_set (MonoInternalThread *thread)
}
}
+static inline void
+lock_thread (MonoInternalThread *thread)
+{
+ if (!thread->synch_cs)
+ ensure_synch_cs_set (thread);
+
+ g_assert (thread->synch_cs);
+ EnterCriticalSection (thread->synch_cs);
+}
+
+static inline void
+unlock_thread (MonoInternalThread *thread)
+{
+ LeaveCriticalSection (thread->synch_cs);
+}
+
/*
* NOTE: this function can be called also for threads different from the current one:
* make sure no code called from it will ever assume it is run on the thread that is
@@ -366,14 +385,16 @@ static void thread_cleanup (MonoInternalThread *thread)
mono_array_set (thread->cached_culture_info, MonoObject*, i, NULL);
}
- ensure_synch_cs_set (thread);
-
- EnterCriticalSection (thread->synch_cs);
+ if (thread->synch_cs)
+ LOCK_THREAD (thread);
+ else
+ g_assert (shutting_down);
thread->state |= ThreadState_Stopped;
thread->state &= ~ThreadState_Background;
- LeaveCriticalSection (thread->synch_cs);
+ if (thread->synch_cs)
+ UNLOCK_THREAD (thread);
/*
An interruption request has leaked to cleanup. Adjust the global counter.
@@ -429,7 +450,6 @@ static void thread_cleanup (MonoInternalThread *thread)
MONO_GC_UNREGISTER_ROOT (thread->thread_pinning_ref);
thread->thread_pinning_ref = NULL;
}
-
}
static gpointer
@@ -474,13 +494,6 @@ set_current_thread_for_domain (MonoDomain *domain, MonoInternalThread *thread, M
*current_thread_ptr = current;
}
-static MonoInternalThread*
-create_internal_thread_object (void)
-{
- MonoVTable *vt = mono_class_vtable (mono_get_root_domain (), mono_defaults.internal_thread_class);
- return (MonoInternalThread*)mono_gc_alloc_mature (vt);
-}
-
static MonoThread*
create_thread_object (MonoDomain *domain)
{
@@ -496,6 +509,28 @@ new_thread_with_internal (MonoDomain *domain, MonoInternalThread *internal)
return thread;
}
+static MonoInternalThread*
+create_internal_thread (void)
+{
+ MonoInternalThread *thread;
+ MonoVTable *vt;
+
+ vt = mono_class_vtable (mono_get_root_domain (), mono_defaults.internal_thread_class);
+ thread = (MonoInternalThread*)mono_gc_alloc_mature (vt);
+
+ thread->synch_cs = g_new0 (CRITICAL_SECTION, 1);
+ InitializeCriticalSection (thread->synch_cs);
+
+ thread->apartment_state = ThreadApartmentState_Unknown;
+ thread->managed_id = get_next_managed_thread_id ();
+ if (mono_gc_is_moving ()) {
+ thread->thread_pinning_ref = thread;
+ MONO_GC_REGISTER_ROOT_PINNING (thread->thread_pinning_ref);
+ }
+
+ return thread;
+}
+
static void
init_root_domain_thread (MonoInternalThread *thread, MonoThread *candidate)
{
@@ -511,7 +546,7 @@ init_root_domain_thread (MonoInternalThread *thread, MonoThread *candidate)
static guint32 WINAPI start_wrapper_internal(void *data)
{
MonoThreadInfo *info;
- struct StartInfo *start_info=(struct StartInfo *)data;
+ StartInfo *start_info = (StartInfo *)data;
guint32 (*start_func)(void *);
void *start_arg;
gsize tid;
@@ -653,106 +688,53 @@ static guint32 WINAPI start_wrapper(void *data)
return start_wrapper_internal (data);
}
-void mono_thread_new_init (intptr_t tid, gpointer stack_start, gpointer func)
-{
- if (mono_thread_start_cb) {
- mono_thread_start_cb (tid, stack_start, func);
- }
-}
-
-void mono_threads_set_default_stacksize (guint32 stacksize)
-{
- default_stacksize = stacksize;
-}
-
-guint32 mono_threads_get_default_stacksize (void)
-{
- return default_stacksize;
-}
-
/*
- * mono_create_thread:
+ * create_thread:
*
- * This is a wrapper around CreateThread which handles differences in the type of
- * the the 'tid' argument.
+ * Common thread creation code.
+ * LOCKING: Acquires the threads lock.
*/
-gpointer mono_create_thread (WapiSecurityAttributes *security,
- guint32 stacksize, WapiThreadStart start,
- gpointer param, guint32 create, gsize *tid)
-{
- gpointer res;
-
-#ifdef HOST_WIN32
- DWORD real_tid;
-
- res = mono_threads_CreateThread (security, stacksize, start, param, create, &real_tid);
- if (tid)
- *tid = real_tid;
-#else
- res = CreateThread (security, stacksize, start, param, create, tid);
-#endif
-
- return res;
-}
-
-/*
- * The thread start argument may be an object reference, and there is
- * no ref to keep it alive when the new thread is started but not yet
- * registered with the collector. So we store it in a GC tracked hash
- * table.
- *
- * LOCKING: Assumes the threads lock is held.
- */
-static void
-register_thread_start_argument (MonoThread *thread, struct StartInfo *start_info)
-{
- if (thread_start_args == NULL) {
- MONO_GC_REGISTER_ROOT_FIXED (thread_start_args);
- thread_start_args = mono_g_hash_table_new (NULL, NULL);
- }
- mono_g_hash_table_insert (thread_start_args, thread, start_info->start_arg);
-}
-
-/*
- * mono_thread_create_internal:
- *
- * If NO_DETACH is TRUE, then the thread is not detached using pthread_detach (). This is needed to fix the race condition where waiting for a thred to exit only waits for its exit event to be
- * signalled, which can cause shutdown crashes if the thread shutdown code accesses data already freed by the runtime shutdown.
- * Currently, this is only used for the finalizer thread.
- */
-MonoInternalThread*
-mono_thread_create_internal (MonoDomain *domain, gpointer func, gpointer arg, gboolean threadpool_thread, gboolean no_detach, guint32 stack_size)
+static gboolean
+create_thread (MonoThread *thread, MonoInternalThread *internal, StartInfo *start_info, gboolean threadpool_thread, gboolean no_detach, guint32 stack_size,
+ gboolean throw_on_failure)
{
- MonoThread *thread;
- MonoInternalThread *internal;
HANDLE thread_handle;
- struct StartInfo *start_info;
- gsize tid;
+ MonoNativeThreadId tid;
guint32 create_flags;
- thread = create_thread_object (domain);
- internal = create_internal_thread_object ();
- MONO_OBJECT_SETREF (thread, internal_thread, internal);
-
- start_info=g_new0 (struct StartInfo, 1);
- start_info->func = func;
- start_info->obj = thread;
- start_info->start_arg = arg;
-
mono_threads_lock ();
if (shutting_down) {
- mono_threads_unlock ();
g_free (start_info);
- return NULL;
+ mono_threads_unlock ();
+ return FALSE;
+ }
+ /*
+ * The thread start argument may be an object reference, and there is
+ * no ref to keep it alive when the new thread is started but not yet
+ * registered with the collector. So we store it in a GC tracked hash
+ * table.
+ */
+ if (thread_start_args == NULL) {
+ MONO_GC_REGISTER_ROOT_FIXED (thread_start_args);
+ thread_start_args = mono_g_hash_table_new (NULL, NULL);
}
+ mono_g_hash_table_insert (thread_start_args, thread, start_info->start_arg);
if (threads_starting_up == NULL) {
MONO_GC_REGISTER_ROOT_FIXED (threads_starting_up);
threads_starting_up = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_VALUE_GC);
}
+ mono_g_hash_table_insert (threads_starting_up, thread, thread);
+ mono_threads_unlock ();
- register_thread_start_argument (thread, start_info);
- mono_g_hash_table_insert (threads_starting_up, thread, thread);
- mono_threads_unlock ();
+ internal->start_notify = CreateSemaphore (NULL, 0, 0x7fffffff, NULL);
+ if (!internal->start_notify) {
+ mono_threads_lock ();
+ mono_g_hash_table_remove (threads_starting_up, thread);
+ mono_threads_unlock ();
+ g_warning ("%s: CreateSemaphore error 0x%x", __func__, GetLastError ());
+ g_free (start_info);
+ return FALSE;
+ }
if (stack_size == 0)
stack_size = default_stacksize_for_thread (internal);
@@ -765,37 +747,103 @@ mono_thread_create_internal (MonoDomain *domain, gpointer func, gpointer arg, gb
if (no_detach)
create_flags |= CREATE_NO_DETACH;
#endif
- thread_handle = mono_create_thread (NULL, stack_size, (LPTHREAD_START_ROUTINE)start_wrapper, start_info,
- create_flags, &tid);
- THREAD_DEBUG (g_message ("%s: Started thread ID %"G_GSIZE_FORMAT" (handle %p)", __func__, tid, thread_handle));
+ thread_handle = mono_threads_create_thread ((LPTHREAD_START_ROUTINE)start_wrapper, start_info,
+ stack_size, create_flags, &tid);
if (thread_handle == NULL) {
/* The thread couldn't be created, so throw an exception */
mono_threads_lock ();
mono_g_hash_table_remove (threads_starting_up, thread);
mono_threads_unlock ();
g_free (start_info);
- mono_raise_exception (mono_get_exception_execution_engine ("Couldn't create thread"));
- return NULL;
- }
-
- internal->handle=thread_handle;
- internal->tid=tid;
- internal->apartment_state=ThreadApartmentState_Unknown;
- internal->managed_id = get_next_managed_thread_id ();
- if (mono_gc_is_moving ()) {
- internal->thread_pinning_ref = internal;
- MONO_GC_REGISTER_ROOT_PINNING (internal->thread_pinning_ref);
+ if (throw_on_failure)
+ mono_raise_exception (mono_get_exception_execution_engine ("Couldn't create thread"));
+ else
+ g_warning ("%s: CreateThread error 0x%x", __func__, GetLastError ());
+ return FALSE;
}
+ THREAD_DEBUG (g_message ("%s: Started thread ID %"G_GSIZE_FORMAT" (handle %p)", __func__, tid, thread_handle));
- internal->synch_cs = g_new0 (CRITICAL_SECTION, 1);
- InitializeCriticalSection (internal->synch_cs);
+ internal->handle = thread_handle;
+ internal->tid = MONO_NATIVE_THREAD_ID_TO_UINT (tid);
internal->threadpool_thread = threadpool_thread;
if (threadpool_thread)
mono_thread_set_state (internal, ThreadState_Background);
- if (handle_store (thread, FALSE))
- ResumeThread (thread_handle);
+ THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Launching thread %p (%"G_GSIZE_FORMAT")", __func__, GetCurrentThreadId (), internal, (gsize)internal->tid));
+
+ /* Only store the handle when the thread is about to be
+ * launched, to avoid the main thread deadlocking while trying
+ * to clean up a thread that will never be signalled.
+ */
+ if (!handle_store (thread, FALSE))
+ return FALSE;
+
+ ResumeThread (internal->handle);
+
+ if (internal->start_notify) {
+ /*
+ * Wait for the thread to set up its TLS data etc, so
+ * theres no potential race condition if someone tries
+ * to look up the data believing the thread has
+ * started
+ */
+ THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") waiting for thread %p (%"G_GSIZE_FORMAT") to start", __func__, GetCurrentThreadId (), internal, (gsize)internal->tid));
+
+ WaitForSingleObjectEx (internal->start_notify, INFINITE, FALSE);
+ CloseHandle (internal->start_notify);
+ internal->start_notify = NULL;
+ }
+
+ THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Done launching thread %p (%"G_GSIZE_FORMAT")", __func__, GetCurrentThreadId (), internal, (gsize)internal->tid));
+
+ return TRUE;
+}
+
+void mono_thread_new_init (intptr_t tid, gpointer stack_start, gpointer func)
+{
+ if (mono_thread_start_cb) {
+ mono_thread_start_cb (tid, stack_start, func);
+ }
+}
+
+void mono_threads_set_default_stacksize (guint32 stacksize)
+{
+ default_stacksize = stacksize;
+}
+
+guint32 mono_threads_get_default_stacksize (void)
+{
+ return default_stacksize;
+}
+
+/*
+ * mono_thread_create_internal:
+ *
+ * If NO_DETACH is TRUE, then the thread is not detached using pthread_detach (). This is needed to fix the race condition where waiting for a thred to exit only waits for its exit event to be
+ * signalled, which can cause shutdown crashes if the thread shutdown code accesses data already freed by the runtime shutdown.
+ * Currently, this is only used for the finalizer thread.
+ */
+MonoInternalThread*
+mono_thread_create_internal (MonoDomain *domain, gpointer func, gpointer arg, gboolean threadpool_thread, gboolean no_detach, guint32 stack_size)
+{
+ MonoThread *thread;
+ MonoInternalThread *internal;
+ StartInfo *start_info;
+ gboolean res;
+
+ thread = create_thread_object (domain);
+ internal = create_internal_thread ();
+ MONO_OBJECT_SETREF (thread, internal_thread, internal);
+
+ start_info = g_new0 (StartInfo, 1);
+ start_info->func = func;
+ start_info->obj = thread;
+ start_info->start_arg = arg;
+
+ res = create_thread (thread, internal, start_info, threadpool_thread, no_detach, stack_size, TRUE);
+ if (!res)
+ return NULL;
/* Check that the managed and unmanaged layout of MonoInternalThread matches */
if (mono_check_corlib_version () == NULL)
@@ -810,9 +858,8 @@ mono_thread_create (MonoDomain *domain, gpointer func, gpointer arg)
mono_thread_create_internal (domain, func, arg, FALSE, FALSE, 0);
}
-#if defined(HOST_WIN32) && defined(__GNUC__)
+#if defined(HOST_WIN32) && HAVE_DECL___READFSDWORD==0
static __inline__ __attribute__((always_inline))
-/* This is not defined by gcc */
unsigned long long
__readfsdword (unsigned long offset)
{
@@ -849,6 +896,17 @@ mono_thread_get_stack_bounds (guint8 **staddr, size_t *stsize)
*staddr = (guint8*)pthread_get_stackaddr_np (pthread_self());
*stsize = pthread_get_stacksize_np (pthread_self());
+
+#ifdef TARGET_OSX
+ /*
+ * Mavericks reports stack sizes as 512kb:
+ * http://permalink.gmane.org/gmane.comp.java.openjdk.hotspot.devel/11590
+ * https://bugs.openjdk.java.net/browse/JDK-8020753
+ */
+ if (*stsize == 512 * 1024)
+ *stsize = 2048 * mono_pagesize ();
+#endif
+
/* staddr points to the start of the stack, not the end */
*staddr -= *stsize;
@@ -964,7 +1022,7 @@ mono_thread_attach_full (MonoDomain *domain, gboolean force_attach)
g_error ("Thread %"G_GSIZE_FORMAT" calling into managed code is not registered with the GC. On UNIX, this can be fixed by #include-ing <gc.h> before <pthread.h> in the file containing the thread creation code.", GetCurrentThreadId ());
}
- thread = create_internal_thread_object ();
+ thread = create_internal_thread ();
thread_handle = GetCurrentThread ();
g_assert (thread_handle);
@@ -983,18 +1041,8 @@ mono_thread_attach_full (MonoDomain *domain, gboolean force_attach)
#ifdef PLATFORM_ANDROID
thread->android_tid = (gpointer) gettid ();
#endif
- thread->apartment_state=ThreadApartmentState_Unknown;
- thread->managed_id = get_next_managed_thread_id ();
- if (mono_gc_is_moving ()) {
- thread->thread_pinning_ref = thread;
- MONO_GC_REGISTER_ROOT_PINNING (thread->thread_pinning_ref);
- }
-
thread->stack_ptr = &tid;
- thread->synch_cs = g_new0 (CRITICAL_SECTION, 1);
- InitializeCriticalSection (thread->synch_cs);
-
THREAD_DEBUG (g_message ("%s: Attached thread ID %"G_GSIZE_FORMAT" (handle %p)", __func__, tid, thread_handle));
info = mono_thread_info_current ();
@@ -1079,23 +1127,20 @@ mono_thread_exit ()
void
ves_icall_System_Threading_Thread_ConstructInternalThread (MonoThread *this)
{
- MonoInternalThread *internal = create_internal_thread_object ();
+ MonoInternalThread *internal = create_internal_thread ();
internal->state = ThreadState_Unstarted;
- internal->apartment_state = ThreadApartmentState_Unknown;
- internal->managed_id = get_next_managed_thread_id ();
InterlockedCompareExchangePointer ((gpointer)&this->internal_thread, internal, NULL);
}
-HANDLE ves_icall_System_Threading_Thread_Thread_internal(MonoThread *this,
- MonoObject *start)
+HANDLE
+ves_icall_System_Threading_Thread_Thread_internal (MonoThread *this,
+ MonoObject *start)
{
- guint32 (*start_func)(void *);
- struct StartInfo *start_info;
- HANDLE thread;
- gsize tid;
+ StartInfo *start_info;
MonoInternalThread *internal;
+ gboolean res;
THREAD_DEBUG (g_message("%s: Trying to start a new thread: this (%p) start (%p)", __func__, this, start));
@@ -1103,87 +1148,48 @@ HANDLE ves_icall_System_Threading_Thread_Thread_internal(MonoThread *this,
ves_icall_System_Threading_Thread_ConstructInternalThread (this);
internal = this->internal_thread;
- ensure_synch_cs_set (internal);
-
- EnterCriticalSection (internal->synch_cs);
+ LOCK_THREAD (internal);
if ((internal->state & ThreadState_Unstarted) == 0) {
- LeaveCriticalSection (internal->synch_cs);
+ UNLOCK_THREAD (internal);
mono_raise_exception (mono_get_exception_thread_state ("Thread has already been started."));
return NULL;
}
if ((internal->state & ThreadState_Aborted) != 0) {
- LeaveCriticalSection (internal->synch_cs);
+ UNLOCK_THREAD (internal);
return this;
}
- start_func = NULL;
- {
- /* This is freed in start_wrapper */
- start_info = g_new0 (struct StartInfo, 1);
- start_info->func = start_func;
- start_info->start_arg = this->start_obj; /* FIXME: GC object stored in unmanaged memory */
- start_info->delegate = start;
- start_info->obj = this;
- g_assert (this->obj.vtable->domain == mono_domain_get ());
-
- internal->start_notify=CreateSemaphore (NULL, 0, 0x7fffffff, NULL);
- if (internal->start_notify==NULL) {
- LeaveCriticalSection (internal->synch_cs);
- g_warning ("%s: CreateSemaphore error 0x%x", __func__, GetLastError ());
- g_free (start_info);
- return(NULL);
- }
-
- mono_threads_lock ();
- register_thread_start_argument (this, start_info);
- if (threads_starting_up == NULL) {
- MONO_GC_REGISTER_ROOT_FIXED (threads_starting_up);
- threads_starting_up = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_VALUE_GC);
- }
- mono_g_hash_table_insert (threads_starting_up, this, this);
- mono_threads_unlock ();
-
- thread=mono_create_thread(NULL, default_stacksize_for_thread (internal), (LPTHREAD_START_ROUTINE)start_wrapper, start_info,
- CREATE_SUSPENDED, &tid);
- if(thread==NULL) {
- LeaveCriticalSection (internal->synch_cs);
- mono_threads_lock ();
- mono_g_hash_table_remove (threads_starting_up, this);
- mono_threads_unlock ();
- g_warning("%s: CreateThread error 0x%x", __func__, GetLastError());
- return(NULL);
- }
-
- internal->handle=thread;
- internal->tid=tid;
- if (mono_gc_is_moving ()) {
- internal->thread_pinning_ref = internal;
- MONO_GC_REGISTER_ROOT_PINNING (internal->thread_pinning_ref);
- }
-
-
- /* Don't call handle_store() here, delay it to Start.
- * We can't join a thread (trying to will just block
- * forever) until it actually starts running, so don't
- * store the handle till then.
- */
+ /* This is freed in start_wrapper */
+ start_info = g_new0 (StartInfo, 1);
+ start_info->func = NULL;
+ start_info->start_arg = this->start_obj; /* FIXME: GC object stored in unmanaged memory */
+ start_info->delegate = start;
+ start_info->obj = this;
+ g_assert (this->obj.vtable->domain == mono_domain_get ());
+
+ res = create_thread (this, internal, start_info, FALSE, FALSE, 0, FALSE);
+ if (!res) {
+ UNLOCK_THREAD (internal);
+ return NULL;
+ }
- mono_thread_start (this);
-
- internal->state &= ~ThreadState_Unstarted;
+ internal->state &= ~ThreadState_Unstarted;
- THREAD_DEBUG (g_message ("%s: Started thread ID %"G_GSIZE_FORMAT" (handle %p)", __func__, tid, thread));
+ THREAD_DEBUG (g_message ("%s: Started thread ID %"G_GSIZE_FORMAT" (handle %p)", __func__, tid, thread));
- LeaveCriticalSection (internal->synch_cs);
- return(thread);
- }
+ UNLOCK_THREAD (internal);
+ return internal->handle;
}
-void ves_icall_System_Threading_InternalThread_Thread_free_internal (MonoInternalThread *this, HANDLE thread)
+/*
+ * This is called from the finalizer of the internal thread object. Since threads keep a reference to their
+ * thread object while running, by the time this function is called, the thread has already exited/detached,
+ * i.e. thread_cleanup () has ran.
+ */
+void
+ves_icall_System_Threading_InternalThread_Thread_free_internal (MonoInternalThread *this, HANDLE thread)
{
- MONO_ARCH_SAVE_REGS;
-
THREAD_DEBUG (g_message ("%s: Closing thread %p, handle %p", __func__, this, thread));
if (thread)
@@ -1203,38 +1209,6 @@ void ves_icall_System_Threading_InternalThread_Thread_free_internal (MonoInterna
}
}
-static void mono_thread_start (MonoThread *thread)
-{
- MonoInternalThread *internal = thread->internal_thread;
-
- THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Launching thread %p (%"G_GSIZE_FORMAT")", __func__, GetCurrentThreadId (), internal, (gsize)internal->tid));
-
- /* Only store the handle when the thread is about to be
- * launched, to avoid the main thread deadlocking while trying
- * to clean up a thread that will never be signalled.
- */
- if (!handle_store (thread, FALSE))
- return;
-
- ResumeThread (internal->handle);
-
- if(internal->start_notify!=NULL) {
- /* Wait for the thread to set up its TLS data etc, so
- * theres no potential race condition if someone tries
- * to look up the data believing the thread has
- * started
- */
-
- THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") waiting for thread %p (%"G_GSIZE_FORMAT") to start", __func__, GetCurrentThreadId (), internal, (gsize)internal->tid));
-
- WaitForSingleObjectEx (internal->start_notify, INFINITE, FALSE);
- CloseHandle (internal->start_notify);
- internal->start_notify = NULL;
- }
-
- THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Done launching thread %p (%"G_GSIZE_FORMAT")", __func__, GetCurrentThreadId (), internal, (gsize)internal->tid));
-}
-
void ves_icall_System_Threading_Thread_Sleep_internal(gint32 ms)
{
guint32 res;
@@ -1273,8 +1247,6 @@ void ves_icall_System_Threading_Thread_SpinWait_nop (void)
gint32
ves_icall_System_Threading_Thread_GetDomainID (void)
{
- MONO_ARCH_SAVE_REGS;
-
return mono_domain_get()->domain_id;
}
@@ -1300,9 +1272,7 @@ mono_thread_get_name (MonoInternalThread *this_obj, guint32 *name_len)
{
gunichar2 *res;
- ensure_synch_cs_set (this_obj);
-
- EnterCriticalSection (this_obj->synch_cs);
+ LOCK_THREAD (this_obj);
if (!this_obj->name) {
*name_len = 0;
@@ -1313,7 +1283,7 @@ mono_thread_get_name (MonoInternalThread *this_obj, guint32 *name_len)
memcpy (res, this_obj->name, sizeof (gunichar2) * this_obj->name_len);
}
- LeaveCriticalSection (this_obj->synch_cs);
+ UNLOCK_THREAD (this_obj);
return res;
}
@@ -1323,16 +1293,14 @@ ves_icall_System_Threading_Thread_GetName_internal (MonoInternalThread *this_obj
{
MonoString* str;
- ensure_synch_cs_set (this_obj);
-
- EnterCriticalSection (this_obj->synch_cs);
+ LOCK_THREAD (this_obj);
if (!this_obj->name)
str = NULL;
else
str = mono_string_new_utf16 (mono_domain_get (), this_obj->name, this_obj->name_len);
- LeaveCriticalSection (this_obj->synch_cs);
+ UNLOCK_THREAD (this_obj);
return str;
}
@@ -1340,12 +1308,10 @@ ves_icall_System_Threading_Thread_GetName_internal (MonoInternalThread *this_obj
void
mono_thread_set_name_internal (MonoInternalThread *this_obj, MonoString *name, gboolean managed)
{
- ensure_synch_cs_set (this_obj);
-
- EnterCriticalSection (this_obj->synch_cs);
+ LOCK_THREAD (this_obj);
if (this_obj->flags & MONO_THREAD_FLAG_NAME_SET) {
- LeaveCriticalSection (this_obj->synch_cs);
+ UNLOCK_THREAD (this_obj);
mono_raise_exception (mono_get_exception_invalid_operation ("Thread.Name can only be set once."));
return;
@@ -1361,7 +1327,8 @@ mono_thread_set_name_internal (MonoInternalThread *this_obj, MonoString *name, g
if (managed)
this_obj->flags |= MONO_THREAD_FLAG_NAME_SET;
- LeaveCriticalSection (this_obj->synch_cs);
+ UNLOCK_THREAD (this_obj);
+
if (this_obj->name) {
char *tname = mono_string_to_utf8 (name);
mono_profiler_thread_name (this_obj->tid, tname);
@@ -1389,7 +1356,7 @@ byte_array_to_domain (MonoArray *arr, MonoDomain *domain)
return arr;
copy = mono_array_new (domain, mono_defaults.byte_class, arr->max_length);
- mono_gc_memmove (mono_array_addr (copy, guint8, 0), mono_array_addr (arr, guint8, 0), arr->max_length);
+ memmove (mono_array_addr (copy, guint8, 0), mono_array_addr (arr, guint8, 0), arr->max_length);
return copy;
}
@@ -1438,18 +1405,16 @@ gboolean ves_icall_System_Threading_Thread_Join_internal(MonoInternalThread *thi
mono_thread_current_check_pending_interrupt ();
- ensure_synch_cs_set (this);
-
- EnterCriticalSection (this->synch_cs);
+ LOCK_THREAD (this);
if ((this->state & ThreadState_Unstarted) != 0) {
- LeaveCriticalSection (this->synch_cs);
+ UNLOCK_THREAD (this);
mono_raise_exception (mono_get_exception_thread_state ("Thread has not been started."));
return FALSE;
}
- LeaveCriticalSection (this->synch_cs);
+ UNLOCK_THREAD (this);
if(ms== -1) {
ms=INFINITE;
@@ -1640,8 +1605,6 @@ ves_icall_System_Threading_WaitHandle_SignalAndWait_Internal (HANDLE toSignal, H
guint32 ret;
MonoInternalThread *thread = mono_thread_internal_current ();
- MONO_ARCH_SAVE_REGS;
-
if (ms == -1)
ms = INFINITE;
@@ -1660,8 +1623,6 @@ HANDLE ves_icall_System_Threading_Mutex_CreateMutex_internal (MonoBoolean owned,
{
HANDLE mutex;
- MONO_ARCH_SAVE_REGS;
-
*created = TRUE;
if (name == NULL) {
@@ -1678,8 +1639,6 @@ HANDLE ves_icall_System_Threading_Mutex_CreateMutex_internal (MonoBoolean owned,
}
MonoBoolean ves_icall_System_Threading_Mutex_ReleaseMutex_internal (HANDLE handle ) {
- MONO_ARCH_SAVE_REGS;
-
return(ReleaseMutex (handle));
}
@@ -1689,8 +1648,6 @@ HANDLE ves_icall_System_Threading_Mutex_OpenMutex_internal (MonoString *name,
{
HANDLE ret;
- MONO_ARCH_SAVE_REGS;
-
*error = ERROR_SUCCESS;
ret = OpenMutex (rights, FALSE, mono_string_chars (name));
@@ -1706,8 +1663,6 @@ HANDLE ves_icall_System_Threading_Semaphore_CreateSemaphore_internal (gint32 ini
{
HANDLE sem;
- MONO_ARCH_SAVE_REGS;
-
*created = TRUE;
if (name == NULL) {
@@ -1728,8 +1683,6 @@ gint32 ves_icall_System_Threading_Semaphore_ReleaseSemaphore_internal (HANDLE ha
{
gint32 prevcount;
- MONO_ARCH_SAVE_REGS;
-
*fail = !ReleaseSemaphore (handle, releaseCount, &prevcount);
return (prevcount);
@@ -1739,8 +1692,6 @@ HANDLE ves_icall_System_Threading_Semaphore_OpenSemaphore_internal (MonoString *
{
HANDLE ret;
- MONO_ARCH_SAVE_REGS;
-
*error = ERROR_SUCCESS;
ret = OpenSemaphore (rights, FALSE, mono_string_chars (name));
@@ -1755,8 +1706,6 @@ HANDLE ves_icall_System_Threading_Events_CreateEvent_internal (MonoBoolean manua
{
HANDLE event;
- MONO_ARCH_SAVE_REGS;
-
*created = TRUE;
if (name == NULL) {
@@ -1774,21 +1723,15 @@ HANDLE ves_icall_System_Threading_Events_CreateEvent_internal (MonoBoolean manua
}
gboolean ves_icall_System_Threading_Events_SetEvent_internal (HANDLE handle) {
- MONO_ARCH_SAVE_REGS;
-
return (SetEvent(handle));
}
gboolean ves_icall_System_Threading_Events_ResetEvent_internal (HANDLE handle) {
- MONO_ARCH_SAVE_REGS;
-
return (ResetEvent(handle));
}
void
ves_icall_System_Threading_Events_CloseEvent_internal (HANDLE handle) {
- MONO_ARCH_SAVE_REGS;
-
CloseHandle (handle);
}
@@ -1798,8 +1741,6 @@ HANDLE ves_icall_System_Threading_Events_OpenEvent_internal (MonoString *name,
{
HANDLE ret;
- MONO_ARCH_SAVE_REGS;
-
*error = ERROR_SUCCESS;
ret = OpenEvent (rights, FALSE, mono_string_chars (name));
@@ -1812,53 +1753,46 @@ HANDLE ves_icall_System_Threading_Events_OpenEvent_internal (MonoString *name,
gint32 ves_icall_System_Threading_Interlocked_Increment_Int (gint32 *location)
{
- MONO_ARCH_SAVE_REGS;
-
return InterlockedIncrement (location);
}
gint64 ves_icall_System_Threading_Interlocked_Increment_Long (gint64 *location)
{
- gint64 ret;
-
- MONO_ARCH_SAVE_REGS;
-
- mono_interlocked_lock ();
-
- ret = ++ *location;
-
- mono_interlocked_unlock ();
-
-
- return ret;
+#if SIZEOF_VOID_P == 4
+ if (G_UNLIKELY ((size_t)location & 0x7)) {
+ gint64 ret;
+ mono_interlocked_lock ();
+ (*location)++;
+ ret = *location;
+ mono_interlocked_unlock ();
+ return ret;
+ }
+#endif
+ return InterlockedIncrement64 (location);
}
gint32 ves_icall_System_Threading_Interlocked_Decrement_Int (gint32 *location)
{
- MONO_ARCH_SAVE_REGS;
-
return InterlockedDecrement(location);
}
gint64 ves_icall_System_Threading_Interlocked_Decrement_Long (gint64 * location)
{
- gint64 ret;
-
- MONO_ARCH_SAVE_REGS;
-
- mono_interlocked_lock ();
-
- ret = -- *location;
-
- mono_interlocked_unlock ();
-
- return ret;
+#if SIZEOF_VOID_P == 4
+ if (G_UNLIKELY ((size_t)location & 0x7)) {
+ gint64 ret;
+ mono_interlocked_lock ();
+ (*location)--;
+ ret = *location;
+ mono_interlocked_unlock ();
+ return ret;
+ }
+#endif
+ return InterlockedDecrement64 (location);
}
gint32 ves_icall_System_Threading_Interlocked_Exchange_Int (gint32 *location, gint32 value)
{
- MONO_ARCH_SAVE_REGS;
-
return InterlockedExchange(location, value);
}
@@ -1879,8 +1813,6 @@ gfloat ves_icall_System_Threading_Interlocked_Exchange_Single (gfloat *location,
{
IntFloatUnion val, ret;
- MONO_ARCH_SAVE_REGS;
-
val.fval = value;
ret.ival = InterlockedExchange((gint32 *) location, val.ival);
@@ -1890,54 +1822,32 @@ gfloat ves_icall_System_Threading_Interlocked_Exchange_Single (gfloat *location,
gint64
ves_icall_System_Threading_Interlocked_Exchange_Long (gint64 *location, gint64 value)
{
-#if SIZEOF_VOID_P == 8
- return (gint64) InterlockedExchangePointer((gpointer *) location, (gpointer)value);
-#else
- gint64 res;
-
- /*
- * According to MSDN, this function is only atomic with regards to the
- * other Interlocked functions on 32 bit platforms.
- */
- mono_interlocked_lock ();
- res = *location;
- *location = value;
- mono_interlocked_unlock ();
-
- return res;
+#if SIZEOF_VOID_P == 4
+ if (G_UNLIKELY ((size_t)location & 0x7)) {
+ gint64 ret;
+ mono_interlocked_lock ();
+ ret = *location;
+ *location = value;
+ mono_interlocked_unlock ();
+ return ret;
+ }
#endif
+ return InterlockedExchange64 (location, value);
}
gdouble
ves_icall_System_Threading_Interlocked_Exchange_Double (gdouble *location, gdouble value)
{
-#if SIZEOF_VOID_P == 8
LongDoubleUnion val, ret;
val.fval = value;
- ret.ival = (gint64)InterlockedExchangePointer((gpointer *) location, (gpointer)val.ival);
+ ret.ival = (gint64)InterlockedExchange64((gint64 *) location, val.ival);
return ret.fval;
-#else
- gdouble res;
-
- /*
- * According to MSDN, this function is only atomic with regards to the
- * other Interlocked functions on 32 bit platforms.
- */
- mono_interlocked_lock ();
- res = *location;
- *location = value;
- mono_interlocked_unlock ();
-
- return res;
-#endif
}
gint32 ves_icall_System_Threading_Interlocked_CompareExchange_Int(gint32 *location, gint32 value, gint32 comparand)
{
- MONO_ARCH_SAVE_REGS;
-
return InterlockedCompareExchange(location, value, comparand);
}
@@ -1958,8 +1868,6 @@ gfloat ves_icall_System_Threading_Interlocked_CompareExchange_Single (gfloat *lo
{
IntFloatUnion val, ret, cmp;
- MONO_ARCH_SAVE_REGS;
-
val.fval = value;
cmp.fval = comparand;
ret.ival = InterlockedCompareExchange((gint32 *) location, val.ival, cmp.ival);
@@ -1995,7 +1903,7 @@ gint64
ves_icall_System_Threading_Interlocked_CompareExchange_Long (gint64 *location, gint64 value, gint64 comparand)
{
#if SIZEOF_VOID_P == 4
- if ((size_t)location & 0x7) {
+ if (G_UNLIKELY ((size_t)location & 0x7)) {
gint64 old;
mono_interlocked_lock ();
old = *location;
@@ -2029,63 +1937,44 @@ ves_icall_System_Threading_Interlocked_Exchange_T (MonoObject **location, MonoOb
gint32
ves_icall_System_Threading_Interlocked_Add_Int (gint32 *location, gint32 value)
{
-#if SIZEOF_VOID_P == 8
- /* Should be implemented as a JIT intrinsic */
- mono_raise_exception (mono_get_exception_not_implemented (NULL));
- return 0;
-#else
- gint32 orig;
-
- mono_interlocked_lock ();
- orig = *location;
- *location = orig + value;
- mono_interlocked_unlock ();
-
- return orig + value;
-#endif
+ return InterlockedAdd (location, value);
}
gint64
ves_icall_System_Threading_Interlocked_Add_Long (gint64 *location, gint64 value)
{
-#if SIZEOF_VOID_P == 8
- /* Should be implemented as a JIT intrinsic */
- mono_raise_exception (mono_get_exception_not_implemented (NULL));
- return 0;
-#else
- gint64 orig;
-
- mono_interlocked_lock ();
- orig = *location;
- *location = orig + value;
- mono_interlocked_unlock ();
-
- return orig + value;
+#if SIZEOF_VOID_P == 4
+ if (G_UNLIKELY ((size_t)location & 0x7)) {
+ gint64 ret;
+ mono_interlocked_lock ();
+ *location += value;
+ ret = *location;
+ mono_interlocked_unlock ();
+ return ret;
+ }
#endif
+ return InterlockedAdd64 (location, value);
}
gint64
ves_icall_System_Threading_Interlocked_Read_Long (gint64 *location)
{
-#if SIZEOF_VOID_P == 8
- /* 64 bit reads are already atomic */
- return *location;
-#else
- gint64 res;
-
- mono_interlocked_lock ();
- res = *location;
- mono_interlocked_unlock ();
-
- return res;
+#if SIZEOF_VOID_P == 4
+ if (G_UNLIKELY ((size_t)location & 0x7)) {
+ gint64 ret;
+ mono_interlocked_lock ();
+ ret = *location;
+ mono_interlocked_unlock ();
+ return ret;
+ }
#endif
+ return InterlockedRead64 (location);
}
void
ves_icall_System_Threading_Thread_MemoryBarrier (void)
{
- mono_threads_lock ();
- mono_threads_unlock ();
+ mono_memory_barrier ();
}
void
@@ -2121,13 +2010,11 @@ ves_icall_System_Threading_Thread_GetState (MonoInternalThread* this)
{
guint32 state;
- ensure_synch_cs_set (this);
-
- EnterCriticalSection (this->synch_cs);
+ LOCK_THREAD (this);
state = this->state;
- LeaveCriticalSection (this->synch_cs);
+ UNLOCK_THREAD (this);
return state;
}
@@ -2137,16 +2024,14 @@ void ves_icall_System_Threading_Thread_Interrupt_internal (MonoInternalThread *t
MonoInternalThread *current;
gboolean throw;
- ensure_synch_cs_set (this);
+ LOCK_THREAD (this);
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);
+ UNLOCK_THREAD (this);
if (throw) {
abort_thread_internal (this, TRUE, FALSE);
@@ -2158,18 +2043,14 @@ void mono_thread_current_check_pending_interrupt ()
MonoInternalThread *thread = mono_thread_internal_current ();
gboolean throw = FALSE;
- mono_debugger_check_interruption ();
-
- ensure_synch_cs_set (thread);
-
- EnterCriticalSection (thread->synch_cs);
+ LOCK_THREAD (thread);
if (thread->thread_interrupt_requested) {
throw = TRUE;
thread->thread_interrupt_requested = FALSE;
}
- LeaveCriticalSection (thread->synch_cs);
+ UNLOCK_THREAD (thread);
if (throw) {
mono_raise_exception (mono_get_exception_thread_interrupted ());
@@ -2251,21 +2132,19 @@ static void signal_thread_state_change (MonoInternalThread *thread)
void
ves_icall_System_Threading_Thread_Abort (MonoInternalThread *thread, MonoObject *state)
{
- ensure_synch_cs_set (thread);
-
- EnterCriticalSection (thread->synch_cs);
+ LOCK_THREAD (thread);
if ((thread->state & ThreadState_AbortRequested) != 0 ||
(thread->state & ThreadState_StopRequested) != 0 ||
(thread->state & ThreadState_Stopped) != 0)
{
- LeaveCriticalSection (thread->synch_cs);
+ UNLOCK_THREAD (thread);
return;
}
if ((thread->state & ThreadState_Unstarted) != 0) {
thread->state |= ThreadState_Aborted;
- LeaveCriticalSection (thread->synch_cs);
+ UNLOCK_THREAD (thread);
return;
}
@@ -2288,7 +2167,7 @@ ves_icall_System_Threading_Thread_Abort (MonoInternalThread *thread, MonoObject
* a problem.
*/
- LeaveCriticalSection (thread->synch_cs);
+ UNLOCK_THREAD (thread);
THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Abort requested for %p (%"G_GSIZE_FORMAT")", __func__, GetCurrentThreadId (), thread, (gsize)thread->tid));
@@ -2306,12 +2185,10 @@ ves_icall_System_Threading_Thread_ResetAbort (void)
MonoInternalThread *thread = mono_thread_internal_current ();
gboolean was_aborting;
- ensure_synch_cs_set (thread);
-
- EnterCriticalSection (thread->synch_cs);
+ LOCK_THREAD (thread);
was_aborting = thread->state & ThreadState_AbortRequested;
thread->state &= ~ThreadState_AbortRequested;
- LeaveCriticalSection (thread->synch_cs);
+ UNLOCK_THREAD (thread);
if (!was_aborting) {
const char *msg = "Unable to reset abort because no abort was requested";
@@ -2329,9 +2206,7 @@ ves_icall_System_Threading_Thread_ResetAbort (void)
void
mono_thread_internal_reset_abort (MonoInternalThread *thread)
{
- ensure_synch_cs_set (thread);
-
- EnterCriticalSection (thread->synch_cs);
+ LOCK_THREAD (thread);
thread->state &= ~ThreadState_AbortRequested;
@@ -2345,7 +2220,7 @@ mono_thread_internal_reset_abort (MonoInternalThread *thread)
}
}
- LeaveCriticalSection (thread->synch_cs);
+ UNLOCK_THREAD (thread);
}
MonoObject*
@@ -2380,15 +2255,13 @@ ves_icall_System_Threading_Thread_GetAbortExceptionState (MonoThread *this)
static gboolean
mono_thread_suspend (MonoInternalThread *thread)
{
- ensure_synch_cs_set (thread);
-
- EnterCriticalSection (thread->synch_cs);
+ LOCK_THREAD (thread);
if ((thread->state & ThreadState_Unstarted) != 0 ||
(thread->state & ThreadState_Aborted) != 0 ||
(thread->state & ThreadState_Stopped) != 0)
{
- LeaveCriticalSection (thread->synch_cs);
+ UNLOCK_THREAD (thread);
return FALSE;
}
@@ -2396,13 +2269,13 @@ mono_thread_suspend (MonoInternalThread *thread)
(thread->state & ThreadState_SuspendRequested) != 0 ||
(thread->state & ThreadState_StopRequested) != 0)
{
- LeaveCriticalSection (thread->synch_cs);
+ UNLOCK_THREAD (thread);
return TRUE;
}
thread->state |= ThreadState_SuspendRequested;
- LeaveCriticalSection (thread->synch_cs);
+ UNLOCK_THREAD (thread);
suspend_thread_internal (thread, FALSE);
return TRUE;
@@ -2418,13 +2291,11 @@ ves_icall_System_Threading_Thread_Suspend (MonoInternalThread *thread)
static gboolean
mono_thread_resume (MonoInternalThread *thread)
{
- ensure_synch_cs_set (thread);
-
- EnterCriticalSection (thread->synch_cs);
+ LOCK_THREAD (thread);
if ((thread->state & ThreadState_SuspendRequested) != 0) {
thread->state &= ~ThreadState_SuspendRequested;
- LeaveCriticalSection (thread->synch_cs);
+ UNLOCK_THREAD (thread);
return TRUE;
}
@@ -2433,7 +2304,7 @@ mono_thread_resume (MonoInternalThread *thread)
(thread->state & ThreadState_Aborted) != 0 ||
(thread->state & ThreadState_Stopped) != 0)
{
- LeaveCriticalSection (thread->synch_cs);
+ UNLOCK_THREAD (thread);
return FALSE;
}
@@ -2482,14 +2353,12 @@ is_running_protected_wrapper (void)
void mono_thread_internal_stop (MonoInternalThread *thread)
{
- ensure_synch_cs_set (thread);
-
- EnterCriticalSection (thread->synch_cs);
+ LOCK_THREAD (thread);
if ((thread->state & ThreadState_StopRequested) != 0 ||
(thread->state & ThreadState_Stopped) != 0)
{
- LeaveCriticalSection (thread->synch_cs);
+ UNLOCK_THREAD (thread);
return;
}
@@ -2499,7 +2368,7 @@ void mono_thread_internal_stop (MonoInternalThread *thread)
thread->state |= ThreadState_StopRequested;
thread->state &= ~ThreadState_AbortRequested;
- LeaveCriticalSection (thread->synch_cs);
+ UNLOCK_THREAD (thread);
abort_thread_internal (thread, TRUE, TRUE);
}
@@ -2512,108 +2381,262 @@ void mono_thread_stop (MonoThread *thread)
gint8
ves_icall_System_Threading_Thread_VolatileRead1 (void *ptr)
{
- return *((volatile gint8 *) (ptr));
+ gint8 tmp;
+ mono_atomic_load_acquire (tmp, gint8, (volatile gint8 *) ptr);
+ return tmp;
}
gint16
ves_icall_System_Threading_Thread_VolatileRead2 (void *ptr)
{
- return *((volatile gint16 *) (ptr));
+ gint16 tmp;
+ mono_atomic_load_acquire (tmp, gint16, (volatile gint16 *) ptr);
+ return tmp;
}
gint32
ves_icall_System_Threading_Thread_VolatileRead4 (void *ptr)
{
- return *((volatile gint32 *) (ptr));
+ gint32 tmp;
+ mono_atomic_load_acquire (tmp, gint32, (volatile gint32 *) ptr);
+ return tmp;
}
gint64
ves_icall_System_Threading_Thread_VolatileRead8 (void *ptr)
{
-#if SIZEOF_VOID_P == 8
- return *((volatile gint64 *) (ptr));
-#else
- return InterlockedCompareExchange64 (ptr, 0, 0); /*Must ensure atomicity of the operation. */
-#endif
+ gint64 tmp;
+ mono_atomic_load_acquire (tmp, gint64, (volatile gint64 *) ptr);
+ return tmp;
}
void *
ves_icall_System_Threading_Thread_VolatileReadIntPtr (void *ptr)
{
- return (void *) *((volatile void **) ptr);
+ volatile void *tmp;
+ mono_atomic_load_acquire (tmp, volatile void *, (volatile void **) ptr);
+ return (void *) tmp;
+}
+
+void *
+ves_icall_System_Threading_Thread_VolatileReadObject (void *ptr)
+{
+ volatile MonoObject *tmp;
+ mono_atomic_load_acquire (tmp, volatile MonoObject *, (volatile MonoObject **) ptr);
+ return (MonoObject *) tmp;
}
double
ves_icall_System_Threading_Thread_VolatileReadDouble (void *ptr)
{
- return *((volatile double *) (ptr));
+ double tmp;
+ mono_atomic_load_acquire (tmp, double, (volatile double *) ptr);
+ return tmp;
}
float
ves_icall_System_Threading_Thread_VolatileReadFloat (void *ptr)
{
- return *((volatile float *) (ptr));
+ float tmp;
+ mono_atomic_load_acquire (tmp, float, (volatile float *) ptr);
+ return tmp;
+}
+
+gint8
+ves_icall_System_Threading_Volatile_Read1 (void *ptr)
+{
+ return InterlockedRead8 (ptr);
+}
+
+gint16
+ves_icall_System_Threading_Volatile_Read2 (void *ptr)
+{
+ return InterlockedRead16 (ptr);
+}
+
+gint32
+ves_icall_System_Threading_Volatile_Read4 (void *ptr)
+{
+ return InterlockedRead (ptr);
+}
+
+gint64
+ves_icall_System_Threading_Volatile_Read8 (void *ptr)
+{
+#if SIZEOF_VOID_P == 4
+ if (G_UNLIKELY ((size_t)ptr & 0x7)) {
+ gint64 val;
+ mono_interlocked_lock ();
+ val = *(gint64*)ptr;
+ mono_interlocked_unlock ();
+ return val;
+ }
+#endif
+ return InterlockedRead64 (ptr);
+}
+
+void *
+ves_icall_System_Threading_Volatile_ReadIntPtr (void *ptr)
+{
+ return InterlockedReadPointer (ptr);
+}
+
+double
+ves_icall_System_Threading_Volatile_ReadDouble (void *ptr)
+{
+ LongDoubleUnion u;
+
+#if SIZEOF_VOID_P == 4
+ if (G_UNLIKELY ((size_t)ptr & 0x7)) {
+ double val;
+ mono_interlocked_lock ();
+ val = *(double*)ptr;
+ mono_interlocked_unlock ();
+ return val;
+ }
+#endif
+
+ u.ival = InterlockedRead64 (ptr);
+
+ return u.fval;
+}
+
+float
+ves_icall_System_Threading_Volatile_ReadFloat (void *ptr)
+{
+ IntFloatUnion u;
+
+ u.ival = InterlockedRead (ptr);
+
+ return u.fval;
}
MonoObject*
ves_icall_System_Threading_Volatile_Read_T (void *ptr)
{
- return (MonoObject*)*((volatile MonoObject**)ptr);
+ return InterlockedReadPointer (ptr);
}
void
ves_icall_System_Threading_Thread_VolatileWrite1 (void *ptr, gint8 value)
{
- *((volatile gint8 *) ptr) = value;
+ mono_atomic_store_release ((volatile gint8 *) ptr, value);
}
void
ves_icall_System_Threading_Thread_VolatileWrite2 (void *ptr, gint16 value)
{
- *((volatile gint16 *) ptr) = value;
+ mono_atomic_store_release ((volatile gint16 *) ptr, value);
}
void
ves_icall_System_Threading_Thread_VolatileWrite4 (void *ptr, gint32 value)
{
- *((volatile gint32 *) ptr) = value;
+ mono_atomic_store_release ((volatile gint32 *) ptr, value);
}
void
ves_icall_System_Threading_Thread_VolatileWrite8 (void *ptr, gint64 value)
{
- *((volatile gint64 *) ptr) = value;
+ mono_atomic_store_release ((volatile gint64 *) ptr, value);
}
void
ves_icall_System_Threading_Thread_VolatileWriteIntPtr (void *ptr, void *value)
{
- *((volatile void **) ptr) = value;
+ mono_atomic_store_release ((volatile void **) ptr, value);
}
void
-ves_icall_System_Threading_Thread_VolatileWriteObject (void *ptr, void *value)
+ves_icall_System_Threading_Thread_VolatileWriteObject (void *ptr, MonoObject *value)
{
- mono_gc_wbarrier_generic_store (ptr, value);
+ mono_gc_wbarrier_generic_store_atomic (ptr, value);
}
void
ves_icall_System_Threading_Thread_VolatileWriteDouble (void *ptr, double value)
{
- *((volatile double *) ptr) = value;
+ mono_atomic_store_release ((volatile double *) ptr, value);
}
void
ves_icall_System_Threading_Thread_VolatileWriteFloat (void *ptr, float value)
{
- *((volatile float *) ptr) = value;
+ mono_atomic_store_release ((volatile float *) ptr, value);
+}
+
+void
+ves_icall_System_Threading_Volatile_Write1 (void *ptr, gint8 value)
+{
+ InterlockedWrite8 (ptr, value);
+}
+
+void
+ves_icall_System_Threading_Volatile_Write2 (void *ptr, gint16 value)
+{
+ InterlockedWrite16 (ptr, value);
+}
+
+void
+ves_icall_System_Threading_Volatile_Write4 (void *ptr, gint32 value)
+{
+ InterlockedWrite (ptr, value);
+}
+
+void
+ves_icall_System_Threading_Volatile_Write8 (void *ptr, gint64 value)
+{
+#if SIZEOF_VOID_P == 4
+ if (G_UNLIKELY ((size_t)ptr & 0x7)) {
+ mono_interlocked_lock ();
+ *(gint64*)ptr = value;
+ mono_interlocked_unlock ();
+ return;
+ }
+#endif
+
+ InterlockedWrite64 (ptr, value);
+}
+
+void
+ves_icall_System_Threading_Volatile_WriteIntPtr (void *ptr, void *value)
+{
+ InterlockedWritePointer (ptr, value);
+}
+
+void
+ves_icall_System_Threading_Volatile_WriteDouble (void *ptr, double value)
+{
+ LongDoubleUnion u;
+
+#if SIZEOF_VOID_P == 4
+ if (G_UNLIKELY ((size_t)ptr & 0x7)) {
+ mono_interlocked_lock ();
+ *(double*)ptr = value;
+ mono_interlocked_unlock ();
+ return;
+ }
+#endif
+
+ u.fval = value;
+
+ InterlockedWrite64 (ptr, u.ival);
+}
+
+void
+ves_icall_System_Threading_Volatile_WriteFloat (void *ptr, float value)
+{
+ IntFloatUnion u;
+
+ u.fval = value;
+
+ InterlockedWrite (ptr, u.ival);
}
void
ves_icall_System_Threading_Volatile_Write_T (void *ptr, MonoObject *value)
{
- *((volatile MonoObject **) ptr) = value;
- mono_gc_wbarrier_generic_nostore (ptr);
+ mono_gc_wbarrier_generic_store_atomic (ptr, value);
}
void
@@ -2915,16 +2938,16 @@ mono_threads_set_shutting_down (void)
/* Make sure we're properly suspended/stopped */
- EnterCriticalSection (current_thread->synch_cs);
+ LOCK_THREAD (current_thread);
if ((current_thread->state & ThreadState_SuspendRequested) ||
(current_thread->state & ThreadState_AbortRequested) ||
(current_thread->state & ThreadState_StopRequested)) {
- LeaveCriticalSection (current_thread->synch_cs);
+ UNLOCK_THREAD (current_thread);
mono_thread_execute_interruption (current_thread);
} else {
current_thread->state |= ThreadState_Stopped;
- LeaveCriticalSection (current_thread->synch_cs);
+ UNLOCK_THREAD (current_thread);
}
/*since we're killing the thread, unset the current domain.*/
@@ -3135,15 +3158,13 @@ void mono_thread_suspend_all_other_threads (void)
continue;
}
- ensure_synch_cs_set (thread);
-
- EnterCriticalSection (thread->synch_cs);
+ LOCK_THREAD (thread);
if (thread->suspended_event == NULL) {
thread->suspended_event = CreateEvent (NULL, TRUE, FALSE, NULL);
if (thread->suspended_event == NULL) {
/* Forget this one and go on to the next */
- LeaveCriticalSection (thread->synch_cs);
+ UNLOCK_THREAD (thread);
continue;
}
}
@@ -3151,7 +3172,7 @@ void mono_thread_suspend_all_other_threads (void)
if ((thread->state & ThreadState_Suspended) != 0 ||
(thread->state & ThreadState_StopRequested) != 0 ||
(thread->state & ThreadState_Stopped) != 0) {
- LeaveCriticalSection (thread->synch_cs);
+ UNLOCK_THREAD (thread);
CloseHandle (wait->handles [i]);
wait->threads [i] = NULL; /* ignore this thread in next loop */
continue;
@@ -3168,7 +3189,7 @@ void mono_thread_suspend_all_other_threads (void)
thread->state |= ThreadState_SuspendRequested;
- LeaveCriticalSection (thread->synch_cs);
+ UNLOCK_THREAD (thread);
/* Signal the thread to suspend */
if (mono_thread_info_new_interrupt_enabled ())
@@ -3186,14 +3207,12 @@ void mono_thread_suspend_all_other_threads (void)
if (thread == NULL)
continue;
- ensure_synch_cs_set (thread);
-
- EnterCriticalSection (thread->synch_cs);
+ LOCK_THREAD (thread);
if ((thread->state & ThreadState_Suspended) != 0) {
CloseHandle (thread->suspended_event);
thread->suspended_event = NULL;
}
- LeaveCriticalSection (thread->synch_cs);
+ UNLOCK_THREAD (thread);
}
}
@@ -3247,7 +3266,7 @@ print_stack_frame_to_string (MonoStackFrameInfo *frame, MonoContext *ctx, gpoint
GString *p = (GString*)data;
MonoMethod *method = NULL;
if (frame->ji)
- method = frame->ji->method;
+ method = mono_jit_info_get_method (frame->ji);
if (method) {
gchar *location = mono_debug_print_stack_frame (method, frame->native_offset, frame->domain);
@@ -3953,7 +3972,7 @@ free_thread_static_data_helper (gpointer key, gpointer value, gpointer user)
if (!thread->static_data || !thread->static_data [idx])
return;
ptr = ((char*) thread->static_data [idx]) + (data->offset & 0xffffff);
- mono_gc_bzero (ptr, data->size);
+ mono_gc_bzero_atomic (ptr, data->size);
}
static void
@@ -4165,9 +4184,7 @@ static guint32 dummy_apc (gpointer param)
*/
static MonoException* mono_thread_execute_interruption (MonoInternalThread *thread)
{
- ensure_synch_cs_set (thread);
-
- EnterCriticalSection (thread->synch_cs);
+ LOCK_THREAD (thread);
/* MonoThread::interruption_requested can only be changed with atomics */
if (InterlockedCompareExchange (&thread->interruption_requested, FALSE, TRUE)) {
@@ -4181,7 +4198,7 @@ static MonoException* mono_thread_execute_interruption (MonoInternalThread *thre
}
if ((thread->state & ThreadState_AbortRequested) != 0) {
- LeaveCriticalSection (thread->synch_cs);
+ UNLOCK_THREAD (thread);
if (thread->abort_exc == NULL) {
/*
* This might be racy, but it has to be called outside the lock
@@ -4198,7 +4215,7 @@ static MonoException* mono_thread_execute_interruption (MonoInternalThread *thre
else if ((thread->state & ThreadState_StopRequested) != 0) {
/* FIXME: do this through the JIT? */
- LeaveCriticalSection (thread->synch_cs);
+ UNLOCK_THREAD (thread);
mono_thread_exit ();
return NULL;
@@ -4208,17 +4225,17 @@ static MonoException* mono_thread_execute_interruption (MonoInternalThread *thre
exc = thread->pending_exception;
thread->pending_exception = NULL;
- LeaveCriticalSection (thread->synch_cs);
+ UNLOCK_THREAD (thread);
return exc;
} else if (thread->thread_interrupt_requested) {
thread->thread_interrupt_requested = FALSE;
- LeaveCriticalSection (thread->synch_cs);
+ UNLOCK_THREAD (thread);
return(mono_get_exception_thread_interrupted ());
}
- LeaveCriticalSection (thread->synch_cs);
+ UNLOCK_THREAD (thread);
return NULL;
}
@@ -4285,10 +4302,9 @@ mono_thread_resume_interruption (void)
if (thread == NULL)
return NULL;
- ensure_synch_cs_set (thread);
- EnterCriticalSection (thread->synch_cs);
+ LOCK_THREAD (thread);
still_aborting = (thread->state & ThreadState_AbortRequested) != 0;
- LeaveCriticalSection (thread->synch_cs);
+ UNLOCK_THREAD (thread);
/*This can happen if the protected block called Thread::ResetAbort*/
if (!still_aborting)
@@ -4323,8 +4339,6 @@ static void mono_thread_interruption_checkpoint_request (gboolean bypass_abort_p
if (thread == NULL)
return;
- mono_debugger_check_interruption ();
-
if (thread->interruption_requested && (bypass_abort_protection || !is_running_protected_wrapper ())) {
MonoException* exc = mono_thread_execute_interruption (thread);
if (exc) mono_raise_exception (exc);
@@ -4445,21 +4459,17 @@ mono_thread_cleanup_apartment_state (void)
void
mono_thread_set_state (MonoInternalThread *thread, MonoThreadState state)
{
- ensure_synch_cs_set (thread);
-
- EnterCriticalSection (thread->synch_cs);
+ LOCK_THREAD (thread);
thread->state |= state;
- LeaveCriticalSection (thread->synch_cs);
+ UNLOCK_THREAD (thread);
}
void
mono_thread_clr_state (MonoInternalThread *thread, MonoThreadState state)
{
- ensure_synch_cs_set (thread);
-
- EnterCriticalSection (thread->synch_cs);
+ LOCK_THREAD (thread);
thread->state &= ~state;
- LeaveCriticalSection (thread->synch_cs);
+ UNLOCK_THREAD (thread);
}
gboolean
@@ -4467,15 +4477,13 @@ mono_thread_test_state (MonoInternalThread *thread, MonoThreadState test)
{
gboolean ret = FALSE;
- ensure_synch_cs_set (thread);
-
- EnterCriticalSection (thread->synch_cs);
+ LOCK_THREAD (thread);
if ((thread->state & test) != 0) {
ret = TRUE;
}
- LeaveCriticalSection (thread->synch_cs);
+ UNLOCK_THREAD (thread);
return ret;
}
@@ -4649,7 +4657,7 @@ abort_thread_internal (MonoInternalThread *thread, gboolean can_raise_exception,
InterlockedIncrement (&thread_interruption_requested);
ji = mono_thread_info_get_last_managed (info);
- protected_wrapper = ji && mono_threads_is_critical_method (ji->method);
+ protected_wrapper = ji && mono_threads_is_critical_method (mono_jit_info_get_method (ji));
running_managed = mono_jit_info_match (ji, MONO_CONTEXT_GET_IP (&info->suspend_state.ctx));
if (!protected_wrapper && running_managed) {
@@ -4690,7 +4698,7 @@ transition_to_suspended (MonoInternalThread *thread)
thread->state |= ThreadState_Suspended;
mono_thread_info_finish_suspend ();
}
- LeaveCriticalSection (thread->synch_cs);
+ UNLOCK_THREAD (thread);
}
static void
@@ -4701,7 +4709,7 @@ suspend_thread_internal (MonoInternalThread *thread, gboolean interrupt)
return;
}
- EnterCriticalSection (thread->synch_cs);
+ LOCK_THREAD (thread);
if (thread == mono_thread_internal_current ()) {
transition_to_suspended (thread);
mono_thread_info_self_suspend ();
@@ -4713,12 +4721,12 @@ suspend_thread_internal (MonoInternalThread *thread, gboolean interrupt)
/*A null info usually means the thread is already dead. */
if (!(info = mono_thread_info_safe_suspend_sync ((MonoNativeThreadId)(gsize)thread->tid, interrupt))) {
- LeaveCriticalSection (thread->synch_cs);
+ UNLOCK_THREAD (thread);
return;
}
ji = mono_thread_info_get_last_managed (info);
- protected_wrapper = ji && mono_threads_is_critical_method (ji->method);
+ protected_wrapper = ji && mono_threads_is_critical_method (mono_jit_info_get_method (ji));
running_managed = mono_jit_info_match (ji, MONO_CONTEXT_GET_IP (&info->suspend_state.ctx));
if (running_managed && !protected_wrapper) {
@@ -4737,7 +4745,7 @@ suspend_thread_internal (MonoInternalThread *thread, gboolean interrupt)
if (interrupt)
wapi_finish_interrupt_thread (interrupt_handle);
#endif
- LeaveCriticalSection (thread->synch_cs);
+ UNLOCK_THREAD (thread);
}
}
}
@@ -4751,13 +4759,13 @@ self_suspend_internal (MonoInternalThread *thread)
thread->state |= ThreadState_Suspended;
thread->suspend_event = CreateEvent (NULL, TRUE, FALSE, NULL);
if (thread->suspend_event == NULL) {
- LeaveCriticalSection (thread->synch_cs);
+ UNLOCK_THREAD (thread);
return;
}
if (thread->suspended_event)
SetEvent (thread->suspended_event);
- LeaveCriticalSection (thread->synch_cs);
+ UNLOCK_THREAD (thread);
if (shutting_down) {
/* After we left the lock, the runtime might shut down so everything becomes invalid */
@@ -4767,7 +4775,7 @@ self_suspend_internal (MonoInternalThread *thread)
WaitForSingleObject (thread->suspend_event, INFINITE);
- EnterCriticalSection (thread->synch_cs);
+ LOCK_THREAD (thread);
CloseHandle (thread->suspend_event);
thread->suspend_event = NULL;
@@ -4778,7 +4786,7 @@ self_suspend_internal (MonoInternalThread *thread)
*/
SetEvent (thread->resume_event);
- LeaveCriticalSection (thread->synch_cs);
+ UNLOCK_THREAD (thread);
return;
}
@@ -4793,14 +4801,14 @@ resume_thread_internal (MonoInternalThread *thread)
if (!mono_thread_info_new_interrupt_enabled ()) {
thread->resume_event = CreateEvent (NULL, TRUE, FALSE, NULL);
if (thread->resume_event == NULL) {
- LeaveCriticalSection (thread->synch_cs);
+ UNLOCK_THREAD (thread);
return FALSE;
}
/* Awake the thread */
SetEvent (thread->suspend_event);
- LeaveCriticalSection (thread->synch_cs);
+ UNLOCK_THREAD (thread);
/* Wait for the thread to awake */
WaitForSingleObject (thread->resume_event, INFINITE);
@@ -4809,13 +4817,13 @@ resume_thread_internal (MonoInternalThread *thread)
return TRUE;
}
- LeaveCriticalSection (thread->synch_cs);
+ UNLOCK_THREAD (thread);
/* Awake the thread */
if (!mono_thread_info_resume ((MonoNativeThreadId)(gpointer)(gsize)thread->tid))
return FALSE;
- EnterCriticalSection (thread->synch_cs);
+ LOCK_THREAD (thread);
thread->state &= ~ThreadState_Suspended;
- LeaveCriticalSection (thread->synch_cs);
+ UNLOCK_THREAD (thread);
return TRUE;
}