X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;ds=sidebyside;f=mono%2Fmetadata%2Fthreads.c;h=c06fc60c9ae2c9926477246b5da7ea877579e0d2;hb=4a2ab0336e97f3591eebbb881a1471d3051946c9;hp=4146391242d3c8589702d6063c4a6d95b72b4c6a;hpb=c6b2a16defbe9fdb8b88bda8e81ac9aa226a3b5f;p=mono.git diff --git a/mono/metadata/threads.c b/mono/metadata/threads.c index 4146391242d..c06fc60c9ae 100644 --- a/mono/metadata/threads.c +++ b/mono/metadata/threads.c @@ -75,9 +75,13 @@ typedef struct { static MonoClassField *wait_handle_os_handle_field = NULL; /* Controls access to the 'threads' hash table */ +#define mono_threads_lock() EnterCriticalSection (&threads_mutex) +#define mono_threads_unlock() LeaveCriticalSection (&threads_mutex) static CRITICAL_SECTION threads_mutex; /* Controls access to context static data */ +#define mono_contexts_lock() EnterCriticalSection (&contexts_mutex) +#define mono_contexts_unlock() LeaveCriticalSection (&contexts_mutex) static CRITICAL_SECTION contexts_mutex; /* Holds current status of static data heap */ @@ -130,6 +134,8 @@ static gboolean mono_thread_resume (MonoThread* thread); static void mono_thread_start (MonoThread *thread); /* Spin lock for InterlockedXXX 64 bit functions */ +#define mono_interlocked_lock() EnterCriticalSection (&interlocked_mutex) +#define mono_interlocked_unlock() LeaveCriticalSection (&interlocked_mutex) static CRITICAL_SECTION interlocked_mutex; /* global count of thread interruptions requested */ @@ -157,9 +163,9 @@ mono_thread_get_tls_offset (void) */ static void handle_store(MonoThread *thread) { - EnterCriticalSection(&threads_mutex); + mono_threads_lock (); - THREAD_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": thread %p ID %d", thread, thread->tid)); + THREAD_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": thread %p ID %"G_GSIZE_FORMAT, thread, (gsize)thread->tid)); if(threads==NULL) { MONO_GC_REGISTER_ROOT (threads); @@ -169,20 +175,23 @@ static void handle_store(MonoThread *thread) /* We don't need to duplicate thread->handle, because it is * only closed when the thread object is finalized by the GC. */ - mono_g_hash_table_insert(threads, GUINT_TO_POINTER(thread->tid), thread); - LeaveCriticalSection(&threads_mutex); + mono_g_hash_table_insert(threads, (gpointer)(gsize)(thread->tid), + thread); + + mono_threads_unlock (); } -static void handle_remove(guint32 tid) +static void handle_remove(gsize tid) { - THREAD_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": thread ID %d", tid)); + THREAD_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": thread ID %"G_GSIZE_FORMAT, tid)); - EnterCriticalSection(&threads_mutex); + mono_threads_lock (); + if (threads) - mono_g_hash_table_remove (threads, GUINT_TO_POINTER(tid)); + mono_g_hash_table_remove (threads, (gpointer)tid); - LeaveCriticalSection(&threads_mutex); + mono_threads_unlock (); /* Don't close the handle here, wait for the object finalizer * to do it. Otherwise, the following race condition applies: @@ -235,7 +244,7 @@ static guint32 WINAPI start_wrapper(void *data) MonoThread *thread=start_info->obj; MonoObject *start_delegate = start_info->delegate; - THREAD_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": (%d) Start wrapper", GetCurrentThreadId ())); + THREAD_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": (%"G_GSIZE_FORMAT") Start wrapper", GetCurrentThreadId ())); /* We can be sure start_info->obj->tid and * start_info->obj->handle have been set, because the thread @@ -264,11 +273,11 @@ static guint32 WINAPI start_wrapper(void *data) thread->stack_ptr = &tid; LIBGC_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION - ": (%d,%d) Setting thread stack to %p", + ": (%"G_GSIZE_FORMAT",%d) Setting thread stack to %p", GetCurrentThreadId (), getpid (), thread->stack_ptr)); THREAD_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION - ": (%d) Setting current_object_key to %p", + ": (%"G_GSIZE_FORMAT") Setting current_object_key to %p", GetCurrentThreadId (), thread)); mono_profiler_thread_start (tid); @@ -287,7 +296,8 @@ static guint32 WINAPI start_wrapper(void *data) thread_adjust_static_data (thread); #ifdef DEBUG - g_message (G_GNUC_PRETTY_FUNCTION "start_wrapper for %d\n", thread->tid); + g_message (G_GNUC_PRETTY_FUNCTION "start_wrapper for %"G_GSIZE_FORMAT, + thread->tid); #endif /* start_func is set only for unamanged start functions */ @@ -306,8 +316,7 @@ static guint32 WINAPI start_wrapper(void *data) * call thread_cleanup() on this thread's behalf. */ - THREAD_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": (%d) Start wrapper terminating", - GetCurrentThreadId ())); + THREAD_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": (%"G_GSIZE_FORMAT") Start wrapper terminating", GetCurrentThreadId ())); /* Remove the reference to the thread object in the TLS data, * so the thread object can be finalized. This won't be @@ -324,7 +333,7 @@ static guint32 WINAPI start_wrapper(void *data) return(0); } -void mono_thread_new_init (guint32 tid, gpointer stack_start, gpointer func) +void mono_thread_new_init (gsize tid, gpointer stack_start, gpointer func) { if (mono_thread_start_cb) { mono_thread_start_cb (tid, stack_start, func); @@ -349,7 +358,7 @@ void mono_thread_create (MonoDomain *domain, gpointer func, gpointer arg) MonoThread *thread; HANDLE thread_handle; struct StartInfo *start_info; - guint32 tid; + gsize tid; thread=(MonoThread *)mono_object_new (domain, mono_defaults.thread_class); @@ -365,7 +374,7 @@ void mono_thread_create (MonoDomain *domain, gpointer func, gpointer arg) */ thread_handle = CreateThread(NULL, default_stacksize_for_thread (thread), (LPTHREAD_START_ROUTINE)start_wrapper, start_info, CREATE_SUSPENDED, &tid); - THREAD_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": Started thread ID %d (handle %p)", + THREAD_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": Started thread ID %"G_GSIZE_FORMAT" (handle %p)", tid, thread_handle)); if (thread_handle == NULL) { /* The thread couldn't be created, so throw an exception */ @@ -388,14 +397,14 @@ mono_thread_attach (MonoDomain *domain) { MonoThread *thread; HANDLE thread_handle; - guint32 tid; + gsize tid; if ((thread = mono_thread_current ())) { /* Already attached */ return thread; } - if (!mono_gc_is_gc_thread ()) { + if (!mono_gc_register_thread (&domain)) { g_error ("Thread %p calling into managed code is not registered with the GC. On UNIX, this can be fixed by #include-ing before in the file containing the thread creation code.", GetCurrentThread ()); } @@ -420,12 +429,12 @@ mono_thread_attach (MonoDomain *domain) thread->tid=tid; thread->synch_lock=mono_object_new (domain, mono_defaults.object_class); - THREAD_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": Attached thread ID %d (handle %p)", + THREAD_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": Attached thread ID %"G_GSIZE_FORMAT" (handle %p)", tid, thread_handle)); handle_store(thread); - THREAD_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": (%d) Setting current_object_key to %p", + THREAD_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": (%"G_GSIZE_FORMAT") Setting current_object_key to %p", GetCurrentThreadId (), thread)); SET_CURRENT_OBJECT (thread); @@ -445,7 +454,7 @@ mono_thread_detach (MonoThread *thread) { g_return_if_fail (thread != NULL); - THREAD_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION "mono_thread_detach for %d\n", thread->tid)); + THREAD_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION "mono_thread_detach for %"G_GSIZE_FORMAT, thread->tid)); SET_CURRENT_OBJECT (NULL); thread_cleanup (thread); @@ -470,9 +479,8 @@ HANDLE ves_icall_System_Threading_Thread_Thread_internal(MonoThread *this, { guint32 (*start_func)(void *); struct StartInfo *start_info; - MonoMethod *im; HANDLE thread; - guint32 tid; + gsize tid; MONO_ARCH_SAVE_REGS; @@ -491,36 +499,12 @@ HANDLE ves_icall_System_Threading_Thread_Thread_internal(MonoThread *this, mono_monitor_exit (this->synch_lock); return this; } -/* FIXME: remove the code inside BROKEN_THREAD_START once martin gets rid of the - * thread_start_compile_func stuff. - */ -#define BROKEN_THREAD_START -#ifdef BROKEN_THREAD_START - im = mono_get_delegate_invoke (start->vtable->klass); - im = mono_marshal_get_delegate_invoke (im); - if (mono_thread_callbacks) - start_func = (* mono_thread_callbacks->thread_start_compile_func) (im); - else - start_func = mono_compile_method (im); - - if(start_func==NULL) { - mono_monitor_exit (this->synch_lock); - g_warning(G_GNUC_PRETTY_FUNCTION - ": Can't locate start method!"); - return(NULL); - } else { -#else start_func = NULL; { -#endif /* This is freed in start_wrapper */ start_info = g_new0 (struct StartInfo, 1); start_info->func = start_func; -#ifdef BROKEN_THREAD_START - start_info->start_arg = start; -#else start_info->start_arg = this->start_obj; -#endif start_info->delegate = start; start_info->obj = this; start_info->domain = mono_domain_get (); @@ -554,8 +538,7 @@ HANDLE ves_icall_System_Threading_Thread_Thread_internal(MonoThread *this, this->state &= ~ThreadState_Unstarted; - THREAD_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION - ": Started thread ID %d (handle %p)", tid, thread)); + THREAD_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": Started thread ID %"G_GSIZE_FORMAT" (handle %p)", tid, thread)); mono_monitor_exit (this->synch_lock); return(thread); @@ -567,8 +550,7 @@ void ves_icall_System_Threading_Thread_Thread_free_internal (MonoThread *this, { MONO_ARCH_SAVE_REGS; - THREAD_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": Closing thread %p, handle %p", - this, thread)); + THREAD_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": Closing thread %p, handle %p", this, thread)); CloseHandle (thread); } @@ -577,8 +559,7 @@ static void mono_thread_start (MonoThread *thread) { MONO_ARCH_SAVE_REGS; - THREAD_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": (%d) Launching thread %p (%d)", - GetCurrentThreadId (), thread, thread->tid)); + THREAD_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": (%"G_GSIZE_FORMAT") Launching thread %p (%"G_GSIZE_FORMAT")", GetCurrentThreadId (), thread, (gsize)thread->tid)); /* Only store the handle when the thread is about to be * launched, to avoid the main thread deadlocking while trying @@ -601,18 +582,14 @@ static void mono_thread_start (MonoThread *thread) * started */ - THREAD_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION - ": (%d) waiting for thread %p (%d) to start", - GetCurrentThreadId (), thread, thread->tid)); + THREAD_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": (%"G_GSIZE_FORMAT") waiting for thread %p (%"G_GSIZE_FORMAT") to start", GetCurrentThreadId (), thread, (gsize)thread->tid)); WaitForSingleObjectEx (thread->start_notify, INFINITE, FALSE); CloseHandle (thread->start_notify); thread->start_notify = NULL; } - THREAD_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION - ": (%d) Done launching thread %p (%d)", - GetCurrentThreadId (), thread, thread->tid)); + THREAD_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": (%"G_GSIZE_FORMAT") Done launching thread %p (%"G_GSIZE_FORMAT")", GetCurrentThreadId (), thread, (gsize)thread->tid)); } void ves_icall_System_Threading_Thread_Sleep_internal(gint32 ms) @@ -922,8 +899,7 @@ gboolean ves_icall_System_Threading_WaitHandle_WaitAll_internal(MonoArray *mono_ g_free(handles); if(ret==WAIT_FAILED) { - THREAD_WAIT_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": (%d) Wait failed", - GetCurrentThreadId ())); + THREAD_WAIT_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": (%"G_GSIZE_FORMAT") Wait failed", GetCurrentThreadId ())); return(FALSE); } else if(ret==WAIT_TIMEOUT || ret == WAIT_IO_COMPLETION) { /* Do we want to try again if we get @@ -931,8 +907,7 @@ gboolean ves_icall_System_Threading_WaitHandle_WaitAll_internal(MonoArray *mono_ * WaitHandle doesn't give any clues. (We'd have to * fiddle with the timeout if we retry.) */ - THREAD_WAIT_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": (%d) Wait timed out", - GetCurrentThreadId ())); + THREAD_WAIT_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": (%"G_GSIZE_FORMAT") Wait timed out", GetCurrentThreadId ())); return(FALSE); } @@ -982,8 +957,7 @@ gint32 ves_icall_System_Threading_WaitHandle_WaitAny_internal(MonoArray *mono_ha g_free(handles); - THREAD_WAIT_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": (%d) returning %d", - GetCurrentThreadId (), ret)); + THREAD_WAIT_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": (%"G_GSIZE_FORMAT") returning %d", GetCurrentThreadId (), ret)); /* * These need to be here. See MSDN dos on WaitForMultipleObjects. @@ -1007,8 +981,7 @@ gboolean ves_icall_System_Threading_WaitHandle_WaitOne_internal(MonoObject *this MONO_ARCH_SAVE_REGS; - THREAD_WAIT_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": (%d) waiting for %p, %d ms", - GetCurrentThreadId (), handle, ms)); + THREAD_WAIT_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": (%"G_GSIZE_FORMAT") waiting for %p, %d ms", GetCurrentThreadId (), handle, ms)); if(ms== -1) { ms=INFINITE; @@ -1025,8 +998,7 @@ gboolean ves_icall_System_Threading_WaitHandle_WaitOne_internal(MonoObject *this mono_monitor_exit (thread->synch_lock); if(ret==WAIT_FAILED) { - THREAD_WAIT_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": (%d) Wait failed", - GetCurrentThreadId ())); + THREAD_WAIT_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": (%"G_GSIZE_FORMAT") Wait failed", GetCurrentThreadId ())); return(FALSE); } else if(ret==WAIT_TIMEOUT || ret == WAIT_IO_COMPLETION) { /* Do we want to try again if we get @@ -1034,8 +1006,7 @@ gboolean ves_icall_System_Threading_WaitHandle_WaitOne_internal(MonoObject *this * WaitHandle doesn't give any clues. (We'd have to * fiddle with the timeout if we retry.) */ - THREAD_WAIT_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": (%d) Wait timed out", - GetCurrentThreadId ())); + THREAD_WAIT_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": (%"G_GSIZE_FORMAT") Wait timed out", GetCurrentThreadId ())); return(FALSE); } @@ -1108,11 +1079,11 @@ gint64 ves_icall_System_Threading_Interlocked_Increment_Long (gint64 *location) MONO_ARCH_SAVE_REGS; - EnterCriticalSection(&interlocked_mutex); + mono_interlocked_lock (); ret = ++ *location; - LeaveCriticalSection(&interlocked_mutex); + mono_interlocked_unlock (); return ret; @@ -1131,11 +1102,11 @@ gint64 ves_icall_System_Threading_Interlocked_Decrement_Long (gint64 * location) MONO_ARCH_SAVE_REGS; - EnterCriticalSection(&interlocked_mutex); + mono_interlocked_lock (); ret = -- *location; - LeaveCriticalSection(&interlocked_mutex); + mono_interlocked_unlock (); return ret; } @@ -1178,10 +1149,10 @@ ves_icall_System_Threading_Interlocked_Exchange_Long (gint64 *location, gint64 v * According to MSDN, this function is only atomic with regards to the * other Interlocked functions on 32 bit platforms. */ - EnterCriticalSection(&interlocked_mutex); + mono_interlocked_lock (); res = *location; *location = value; - LeaveCriticalSection(&interlocked_mutex); + mono_interlocked_unlock (); return res; #endif @@ -1204,10 +1175,10 @@ ves_icall_System_Threading_Interlocked_Exchange_Double (gdouble *location, gdoub * According to MSDN, this function is only atomic with regards to the * other Interlocked functions on 32 bit platforms. */ - EnterCriticalSection(&interlocked_mutex); + mono_interlocked_lock (); res = *location; *location = value; - LeaveCriticalSection(&interlocked_mutex); + mono_interlocked_unlock (); return res; #endif @@ -1254,11 +1225,11 @@ ves_icall_System_Threading_Interlocked_CompareExchange_Double (gdouble *location #else gdouble old; - EnterCriticalSection(&interlocked_mutex); + mono_interlocked_lock (); old = *location; if (old == comparand) *location = value; - LeaveCriticalSection(&interlocked_mutex); + mono_interlocked_unlock (); return old; #endif @@ -1272,11 +1243,11 @@ ves_icall_System_Threading_Interlocked_CompareExchange_Long (gint64 *location, g #else gint64 old; - EnterCriticalSection(&interlocked_mutex); + mono_interlocked_lock (); old = *location; if (old == comparand) *location = value; - LeaveCriticalSection(&interlocked_mutex); + mono_interlocked_unlock (); return old; #endif @@ -1292,10 +1263,10 @@ ves_icall_System_Threading_Interlocked_Add_Int (gint32 *location, gint32 value) #else gint32 orig; - EnterCriticalSection(&interlocked_mutex); + mono_interlocked_lock (); orig = *location; *location = orig + value; - LeaveCriticalSection(&interlocked_mutex); + mono_interlocked_unlock (); return orig; #endif @@ -1311,10 +1282,10 @@ ves_icall_System_Threading_Interlocked_Add_Long (gint64 *location, gint64 value) #else gint64 orig; - EnterCriticalSection(&interlocked_mutex); + mono_interlocked_lock (); orig = *location; *location = orig + value; - LeaveCriticalSection(&interlocked_mutex); + mono_interlocked_unlock (); return orig; #endif @@ -1329,14 +1300,21 @@ ves_icall_System_Threading_Interlocked_Read_Long (gint64 *location) #else gint64 res; - EnterCriticalSection(&interlocked_mutex); + mono_interlocked_lock (); res = *location; - LeaveCriticalSection(&interlocked_mutex); + mono_interlocked_unlock (); return res; #endif } +void +ves_icall_System_Threading_Thread_MemoryBarrier (void) +{ + /* Should be implemented as a JIT intrinsic */ + mono_raise_exception (mono_get_exception_not_implemented (NULL)); +} + void ves_icall_System_Threading_Thread_ClrState (MonoThread* this, guint32 state) { @@ -1386,6 +1364,20 @@ mono_thread_get_abort_signal (void) #ifndef SIGRTMIN return SIGUSR1; #else + static int abort_signum = -1; + int i; + if (abort_signum != -1) + return abort_signum; + /* we try to avoid SIGRTMIN and any one that might have been set already, see bug #75387 */ + for (i = SIGRTMIN + 1; i < SIGRTMAX; ++i) { + struct sigaction sinfo; + sigaction (i, NULL, &sinfo); + if (sinfo.sa_handler == SIG_DFL && (void*)sinfo.sa_sigaction == (void*)SIG_DFL) { + abort_signum = i; + return i; + } + } + /* fallback to the old way */ return SIGRTMIN; #endif #endif /*defined (__MINGW32__) || defined (_MSC_VER) */ @@ -1419,7 +1411,7 @@ static void signal_thread_state_change (MonoThread *thread) #else /* fixme: store the state somewhere */ #ifdef PTHREAD_POINTER_ID - pthread_kill (GUINT_TO_POINTER(thread->tid), mono_thread_get_abort_signal ()); + pthread_kill ((gpointer)(gsize)(thread->tid), mono_thread_get_abort_signal ()); #else pthread_kill (thread->tid, mono_thread_get_abort_signal ()); #endif @@ -1434,7 +1426,8 @@ ves_icall_System_Threading_Thread_Abort (MonoThread *thread, MonoObject *state) mono_monitor_enter (thread->synch_lock); if ((thread->state & ThreadState_AbortRequested) != 0 || - (thread->state & ThreadState_StopRequested) != 0) + (thread->state & ThreadState_StopRequested) != 0 || + (thread->state & ThreadState_Stopped) != 0) { mono_monitor_exit (thread->synch_lock); return; @@ -1452,9 +1445,7 @@ ves_icall_System_Threading_Thread_Abort (MonoThread *thread, MonoObject *state) mono_monitor_exit (thread->synch_lock); - THREAD_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION - ": (%d) Abort requested for %p (%d)", GetCurrentThreadId (), - thread, thread->tid)); + THREAD_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": (%"G_GSIZE_FORMAT") Abort requested for %p (%"G_GSIZE_FORMAT")", GetCurrentThreadId (), thread, (gsize)thread->tid)); /* Make sure the thread is awake */ mono_thread_resume (thread); @@ -1470,7 +1461,7 @@ ves_icall_System_Threading_Thread_ResetAbort (void) MONO_ARCH_SAVE_REGS; mono_monitor_enter (thread->synch_lock); - + thread->state &= ~ThreadState_AbortRequested; if (!thread->abort_exc) { @@ -1603,7 +1594,7 @@ void mono_thread_stop (MonoThread *thread) /* Make sure the thread is awake */ mono_thread_resume (thread); - + thread->state |= ThreadState_StopRequested; thread->state &= ~ThreadState_AbortRequested; @@ -1712,7 +1703,13 @@ void mono_install_thread_callbacks (MonoThreadCallbacks *callbacks) G_GNUC_UNUSED static void print_tids (gpointer key, gpointer value, gpointer user) { - g_message ("Waiting for: %d", GPOINTER_TO_UINT(key)); + /* GPOINTER_TO_UINT breaks horribly if sizeof(void *) > + * sizeof(uint) and a cast to uint would overflow + */ + /* Older versions of glib don't have G_GSIZE_FORMAT, so just + * print this as a pointer. + */ + g_message ("Waiting for: %p", key); } struct wait_data @@ -1744,9 +1741,9 @@ static void wait_for_tids (struct wait_data *wait, guint32 timeout) return; for(i=0; inum; i++) { - guint32 tid=wait->threads[i]->tid; + gsize tid = wait->threads[i]->tid; - if(mono_g_hash_table_lookup (threads, GUINT_TO_POINTER(tid))!=NULL) { + if(mono_g_hash_table_lookup (threads, (gpointer)tid)!=NULL) { /* This thread must have been killed, because * it hasn't cleaned itself up. (It's just * possible that the thread exited before the @@ -1758,8 +1755,7 @@ static void wait_for_tids (struct wait_data *wait, guint32 timeout) * same thread.) */ - THREAD_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION - ": cleaning up after thread %d", tid)); + THREAD_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": cleaning up after thread %"G_GSIZE_FORMAT, tid)); thread_cleanup (wait->threads[i]); } } @@ -1796,17 +1792,16 @@ static void wait_for_tids_or_state_change (struct wait_data *wait, guint32 timeo return; if (ret < wait->num) { - guint32 tid=wait->threads[ret]->tid; - EnterCriticalSection (&threads_mutex); - if (mono_g_hash_table_lookup (threads, GUINT_TO_POINTER(tid))!=NULL) { + gsize tid = wait->threads[ret]->tid; + mono_threads_lock (); + if (mono_g_hash_table_lookup (threads, (gpointer)tid)!=NULL) { /* See comment in wait_for_tids about thread cleanup */ - LeaveCriticalSection (&threads_mutex); + mono_threads_unlock (); THREAD_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION - ": cleaning up after thread %d", tid)); - thread_cleanup (wait->threads[i]); - } - else - LeaveCriticalSection (&threads_mutex); + ": cleaning up after thread %"G_GSIZE_FORMAT, tid)); + thread_cleanup (wait->threads [ret]); + } else + mono_threads_unlock (); } } @@ -1853,10 +1848,13 @@ static gboolean remove_and_abort_threads (gpointer key, gpointer value, gpointer user) { struct wait_data *wait=(struct wait_data *)user; - guint32 self = GetCurrentThreadId (); + gsize self = GetCurrentThreadId (); MonoThread *thread = (MonoThread *) value; HANDLE handle; + if (wait->num >= MAXIMUM_WAIT_OBJECTS) + return FALSE; + /* The finalizer thread is not a background thread */ if (thread->tid != self && (thread->state & ThreadState_Background) != 0) { @@ -1866,15 +1864,16 @@ remove_and_abort_threads (gpointer key, gpointer value, gpointer user) if(thread->state & ThreadState_AbortRequested || thread->state & ThreadState_Aborted) { - THREAD_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": Thread id %d already aborting", thread->tid)); + THREAD_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": Thread id %"G_GSIZE_FORMAT" already aborting", (gsize)thread->tid)); return(TRUE); } + /* printf ("A: %d\n", wait->num); */ wait->handles[wait->num]=thread->handle; wait->threads[wait->num]=thread; wait->num++; - THREAD_DEBUG (g_print (G_GNUC_PRETTY_FUNCTION ": Aborting id: %d\n", thread->tid)); + THREAD_DEBUG (g_print (G_GNUC_PRETTY_FUNCTION ": Aborting id: %"G_GSIZE_FORMAT"\n", (gsize)thread->tid)); mono_thread_stop (thread); return TRUE; } @@ -1889,16 +1888,16 @@ void mono_thread_manage (void) /* join each thread that's still running */ THREAD_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": Joining each running thread...")); - EnterCriticalSection (&threads_mutex); + mono_threads_lock (); if(threads==NULL) { THREAD_DEBUG (g_message(G_GNUC_PRETTY_FUNCTION ": No threads")); - LeaveCriticalSection (&threads_mutex); + mono_threads_unlock (); return; } - LeaveCriticalSection (&threads_mutex); + mono_threads_unlock (); do { - EnterCriticalSection (&threads_mutex); + mono_threads_lock (); THREAD_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ":There are %d threads to join", mono_g_hash_table_size (threads)); mono_g_hash_table_foreach (threads, print_tids, NULL)); @@ -1906,7 +1905,7 @@ void mono_thread_manage (void) ResetEvent (background_change_event); wait->num=0; mono_g_hash_table_foreach (threads, build_wait_tids, wait); - LeaveCriticalSection (&threads_mutex); + mono_threads_unlock (); if(wait->num>0) { /* Something to wait for */ wait_for_tids_or_state_change (wait, INFINITE); @@ -1919,22 +1918,25 @@ void mono_thread_manage (void) THREAD_DEBUG (g_message ("threadpool cleanup")); mono_thread_pool_cleanup (); - EnterCriticalSection(&threads_mutex); - /* * Remove everything but the finalizer thread and self. * Also abort all the background threads * */ - wait->num = 0; - mono_g_hash_table_foreach_remove (threads, remove_and_abort_threads, wait); + do { + mono_threads_lock (); - LeaveCriticalSection(&threads_mutex); + wait->num = 0; + mono_g_hash_table_foreach_remove (threads, remove_and_abort_threads, wait); - THREAD_DEBUG (g_message ("wait->num is now %d", wait->num)); - if(wait->num>0) { - /* Something to wait for */ - wait_for_tids (wait, INFINITE); - } + mono_threads_unlock (); + + THREAD_DEBUG (g_message ("wait->num is now %d", wait->num)); + if(wait->num>0) { + /* Something to wait for */ + wait_for_tids (wait, INFINITE); + } + } while (wait->num > 0); + /* * give the subthreads a chance to really quit (this is mainly needed * to get correct user and system times from getrusage/wait/time(1)). @@ -1950,26 +1952,24 @@ void mono_thread_manage (void) static void terminate_thread (gpointer key, gpointer value, gpointer user) { MonoThread *thread=(MonoThread *)value; - guint32 self=GPOINTER_TO_UINT (user); - if(thread->tid!=self) { + if(thread->tid != (gsize)user) { /*TerminateThread (thread->handle, -1);*/ } } void mono_thread_abort_all_other_threads (void) { - guint32 self=GetCurrentThreadId (); + gsize self = GetCurrentThreadId (); - EnterCriticalSection (&threads_mutex); + mono_threads_lock (); THREAD_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ":There are %d threads to abort", mono_g_hash_table_size (threads)); mono_g_hash_table_foreach (threads, print_tids, NULL)); - mono_g_hash_table_foreach (threads, terminate_thread, - GUINT_TO_POINTER (self)); + mono_g_hash_table_foreach (threads, terminate_thread, (gpointer)self); - LeaveCriticalSection (&threads_mutex); + mono_threads_unlock (); } static void @@ -1999,7 +1999,7 @@ void mono_thread_suspend_all_other_threads (void) { struct wait_data *wait = g_new0 (struct wait_data, 1); int i, waitnum; - guint32 self = GetCurrentThreadId (); + gsize self = GetCurrentThreadId (); gpointer *events; guint32 eventidx = 0; @@ -2007,9 +2007,9 @@ void mono_thread_suspend_all_other_threads (void) * Make a copy of the hashtable since we can't do anything with * threads while threads_mutex is held. */ - EnterCriticalSection (&threads_mutex); + mono_threads_lock (); mono_g_hash_table_foreach (threads, collect_threads, wait); - LeaveCriticalSection (&threads_mutex); + mono_threads_unlock (); events = g_new0 (gpointer, wait->num); waitnum = 0; @@ -2081,10 +2081,10 @@ mono_thread_push_appdomain_ref (MonoDomain *domain) MonoThread *thread = mono_thread_current (); if (thread) { - /* printf ("PUSH REF: %x -> %s.\n", thread->tid, domain->friendly_name); */ - EnterCriticalSection (&threads_mutex); + /* printf ("PUSH REF: %"G_GSIZE_FORMAT" -> %s.\n", (gsize)thread->tid, domain->friendly_name); */ + mono_threads_lock (); thread->appdomain_refs = g_slist_prepend (thread->appdomain_refs, domain); - LeaveCriticalSection (&threads_mutex); + mono_threads_unlock (); } } @@ -2094,12 +2094,12 @@ mono_thread_pop_appdomain_ref (void) MonoThread *thread = mono_thread_current (); if (thread) { - /* printf ("POP REF: %x -> %s.\n", thread->tid, ((MonoDomain*)(thread->appdomain_refs->data))->friendly_name); */ - EnterCriticalSection (&threads_mutex); + /* printf ("POP REF: %"G_GSIZE_FORMAT" -> %s.\n", (gsize)thread->tid, ((MonoDomain*)(thread->appdomain_refs->data))->friendly_name); */ + mono_threads_lock (); /* FIXME: How can the list be empty ? */ if (thread->appdomain_refs) thread->appdomain_refs = g_slist_remove (thread->appdomain_refs, thread->appdomain_refs->data); - LeaveCriticalSection (&threads_mutex); + mono_threads_unlock (); } } @@ -2107,9 +2107,9 @@ gboolean mono_thread_has_appdomain_ref (MonoThread *thread, MonoDomain *domain) { gboolean res; - EnterCriticalSection (&threads_mutex); + mono_threads_lock (); res = g_slist_find (thread->appdomain_refs, domain) != NULL; - LeaveCriticalSection (&threads_mutex); + mono_threads_unlock (); return res; } @@ -2126,11 +2126,12 @@ abort_appdomain_thread (gpointer key, gpointer value, gpointer user_data) MonoDomain *domain = data->domain; if (mono_thread_has_appdomain_ref (thread, domain)) { - /* printf ("ABORTING THREAD %p BECAUSE IT REFERENCES DOMAIN %s.\n", thread->tid, domain->friendly_name); */ HANDLE handle = OpenThread (THREAD_ALL_ACCESS, TRUE, thread->tid); if (handle == NULL) return; + /* printf ("ABORTING THREAD %p BECAUSE IT REFERENCES DOMAIN %s.\n", thread->tid, domain->friendly_name); */ + ves_icall_System_Threading_Thread_Abort (thread, NULL); if(data->wait.num 0) - wait_for_tids (&user_data.wait, timeout); + /* + * We should wait for the threads either to abort, or to leave the + * domain. We can't do the latter, so we wait with a timeout. + */ + wait_for_tids (&user_data.wait, 100); /* Update remaining time */ timeout -= GetTickCount () - start_time; @@ -2216,9 +2221,9 @@ clear_cached_culture (gpointer key, gpointer value, gpointer user_data) void mono_threads_clear_cached_culture (MonoDomain *domain) { - EnterCriticalSection (&threads_mutex); + mono_threads_lock (); mono_g_hash_table_foreach (threads, clear_cached_culture, domain); - LeaveCriticalSection (&threads_mutex); + mono_threads_unlock (); } /* @@ -2338,13 +2343,13 @@ thread_adjust_static_data (MonoThread *thread) { guint32 offset; - EnterCriticalSection (&threads_mutex); + mono_threads_lock (); if (thread_static_info.offset || thread_static_info.idx > 0) { /* get the current allocated size */ offset = thread_static_info.offset | ((thread_static_info.idx + 1) << 24); mono_alloc_static_data (&(thread->static_data), offset); } - LeaveCriticalSection (&threads_mutex); + mono_threads_unlock (); } static void @@ -2370,19 +2375,19 @@ mono_alloc_special_static_data (guint32 static_type, guint32 size, guint32 align guint32 offset; if (static_type == SPECIAL_STATIC_THREAD) { - EnterCriticalSection (&threads_mutex); + mono_threads_lock (); offset = mono_alloc_static_data_slot (&thread_static_info, size, align); /* This can be called during startup */ if (threads != NULL) mono_g_hash_table_foreach (threads, alloc_thread_static_data_helper, GUINT_TO_POINTER (offset)); - LeaveCriticalSection (&threads_mutex); + mono_threads_unlock (); } else { g_assert (static_type == SPECIAL_STATIC_CONTEXT); - EnterCriticalSection (&contexts_mutex); + mono_contexts_lock (); offset = mono_alloc_static_data_slot (&context_static_info, size, align); - LeaveCriticalSection (&contexts_mutex); + mono_contexts_unlock (); offset |= 0x80000000; /* Set the high bit to indicate context static data */ } return offset; @@ -2411,9 +2416,9 @@ mono_get_special_static_data (guint32 offset) */ MonoAppContext *context = mono_context_get (); if (!context->static_data || !context->static_data [idx]) { - EnterCriticalSection (&contexts_mutex); + mono_contexts_lock (); mono_alloc_static_data (&(context->static_data), offset); - LeaveCriticalSection (&contexts_mutex); + mono_contexts_unlock (); } return ((char*) context->static_data [idx]) + (offset & 0xffffff); } @@ -2422,11 +2427,10 @@ mono_get_special_static_data (guint32 offset) static void gc_stop_world (gpointer key, gpointer value, gpointer user) { MonoThread *thread=(MonoThread *)value; - guint32 self=GPOINTER_TO_UINT (user); - LIBGC_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": %d - %d", self, thread->tid)); + LIBGC_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": %"G_GSIZE_FORMAT" - %"G_GSIZE_FORMAT, (gsize)user, (gsize)thread->tid)); - if(thread->tid==self) + if(thread->tid == (gsize)user) return; SuspendThread (thread->handle); @@ -2434,26 +2438,25 @@ static void gc_stop_world (gpointer key, gpointer value, gpointer user) void mono_gc_stop_world (void) { - guint32 self=GetCurrentThreadId (); + gsize self = GetCurrentThreadId (); - LIBGC_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": %d - %p", self, threads)); + LIBGC_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": %"G_GSIZE_FORMAT" - %p", self, threads)); - EnterCriticalSection (&threads_mutex); + mono_threads_lock (); if (threads != NULL) - mono_g_hash_table_foreach (threads, gc_stop_world, GUINT_TO_POINTER (self)); + mono_g_hash_table_foreach (threads, gc_stop_world, (gpointer)self); - LeaveCriticalSection (&threads_mutex); + mono_threads_unlock (); } static void gc_start_world (gpointer key, gpointer value, gpointer user) { MonoThread *thread=(MonoThread *)value; - guint32 self=GPOINTER_TO_UINT (user); - LIBGC_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": %d - %d", self, thread->tid)); + LIBGC_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": %"G_GSIZE_FORMAT" - %"G_GSIZE_FORMAT, (gsize)user, (gsize)thread->tid)); - if(thread->tid==self) + if(thread->tid == (gsize)user) return; ResumeThread (thread->handle); @@ -2461,16 +2464,16 @@ static void gc_start_world (gpointer key, gpointer value, gpointer user) void mono_gc_start_world (void) { - guint32 self=GetCurrentThreadId (); + gsize self = GetCurrentThreadId (); - LIBGC_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": %d - %p", self, threads)); + LIBGC_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": %"G_GSIZE_FORMAT" - %p", self, threads)); - EnterCriticalSection (&threads_mutex); + mono_threads_lock (); if (threads != NULL) - mono_g_hash_table_foreach (threads, gc_start_world, GUINT_TO_POINTER (self)); + mono_g_hash_table_foreach (threads, gc_start_world, (gpointer)self); - LeaveCriticalSection (&threads_mutex); + mono_threads_unlock (); } #ifdef __MINGW32__ @@ -2601,7 +2604,7 @@ static void mono_thread_interruption_checkpoint_request (gboolean bypass_abort_p /* The thread may already be stopping */ if (thread == NULL) return; - + if (thread->interruption_requested && (bypass_abort_protection || !is_running_protected_wrapper ())) { MonoException* exc = mono_thread_execute_interruption (thread); if (exc) mono_raise_exception (exc); @@ -2644,11 +2647,11 @@ gint32* mono_thread_interruption_request_flag () static void gc_push_all_stacks (gpointer key, gpointer value, gpointer user) { MonoThread *thread=(MonoThread *)value; - guint32 *selfp=(guint32 *)user, self = *selfp; + gsize *selfp = (gsize *)user, self = *selfp; - LIBGC_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": %d - %d - %p", self, thread->tid, thread->stack_ptr)); + LIBGC_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": %"G_GSIZE_FORMAT" - %"G_GSIZE_FORMAT" - %p", self, (gsize)thread->tid, thread->stack_ptr)); - if(thread->tid==self) { + if(thread->tid == self) { LIBGC_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": %p - %p", selfp, thread->stack_ptr)); GC_push_all_stack (selfp, thread->stack_ptr); return; @@ -2663,16 +2666,16 @@ static void gc_push_all_stacks (gpointer key, gpointer value, gpointer user) void mono_gc_push_all_stacks (void) { - guint32 self=GetCurrentThreadId (); + gsize self = GetCurrentThreadId (); - LIBGC_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": %d - %p", self, threads)); + LIBGC_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": %"G_GSIZE_FORMAT" - %p", self, threads)); - EnterCriticalSection (&threads_mutex); + mono_threads_lock (); if (threads != NULL) mono_g_hash_table_foreach (threads, gc_push_all_stacks, &self); - LeaveCriticalSection (&threads_mutex); + mono_threads_unlock (); } #endif /* WITH_INCLUDED_LIBGC */