X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fthreads.c;h=96bdefc0bdce864fdc243e8a0fa6e131dcc9be0a;hb=87accf5e934bd049ce7f59b9fab13a151ae88075;hp=bd06079be762cf7cbc619925d736f08272d43872;hpb=3644c9e523205fac5198a21f898ebc3a9dd2ccf7;p=mono.git diff --git a/mono/metadata/threads.c b/mono/metadata/threads.c index bd06079be76..96bdefc0bdc 100644 --- a/mono/metadata/threads.c +++ b/mono/metadata/threads.c @@ -27,6 +27,9 @@ #include #include #include +#ifndef PLATFORM_WIN32 +#include +#endif #include #include #include @@ -419,9 +422,8 @@ static void try_free_delayed_free_item (int index) { if (delayed_free_table->len > index) { - DelayedFreeItem item; + DelayedFreeItem item = { NULL, NULL }; - item.p = NULL; EnterCriticalSection (&delayed_free_table_mutex); /* We have to check the length again because another thread might have freed an item before we acquired @@ -528,6 +530,8 @@ static void thread_cleanup (MonoThread *thread) if (thread->serialized_culture_info) g_free (thread->serialized_culture_info); + g_free (thread->name); + thread->cached_culture_info = NULL; mono_gc_free_fixed (thread->static_data); @@ -591,7 +595,7 @@ static guint32 WINAPI start_wrapper(void *data) /* On 2.0 profile (and higher), set explicitly since state might have been Unknown */ - if (mono_get_runtime_info ()->framework_version [0] != '1') { + if (mono_framework_version () != 1) { if (thread->apartment_state == ThreadApartmentState_Unknown) thread->apartment_state = ThreadApartmentState_MTA; } @@ -731,6 +735,8 @@ void mono_thread_create_internal (MonoDomain *domain, gpointer func, gpointer ar InitializeCriticalSection (thread->synch_cs); thread->threadpool_thread = threadpool_thread; + if (threadpool_thread) + mono_thread_set_state (thread, ThreadState_Background); if (handle_store (thread)) ResumeThread (thread_handle); @@ -754,6 +760,7 @@ 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 = (guint8*)((gssize)*staddr & ~(mono_pagesize () - 1)); return; /* FIXME: simplify the mess below */ #elif !defined(PLATFORM_WIN32) @@ -762,31 +769,31 @@ mono_thread_get_stack_bounds (guint8 **staddr, size_t *stsize) pthread_attr_init (&attr); #ifdef HAVE_PTHREAD_GETATTR_NP - pthread_getattr_np (pthread_self(), &attr); + pthread_getattr_np (pthread_self(), &attr); #else #ifdef HAVE_PTHREAD_ATTR_GET_NP - pthread_attr_get_np (pthread_self(), &attr); + pthread_attr_get_np (pthread_self(), &attr); #elif defined(sun) - *staddr = NULL; - pthread_attr_getstacksize (&attr, &stsize); + *staddr = NULL; + pthread_attr_getstacksize (&attr, &stsize); #else - *staddr = NULL; - *stsize = 0; - return; + *staddr = NULL; + *stsize = 0; + return; #endif #endif #ifndef sun - pthread_attr_getstack (&attr, (void**)staddr, stsize); - if (*staddr) - g_assert ((current > *staddr) && (current < *staddr + *stsize)); + pthread_attr_getstack (&attr, (void**)staddr, stsize); + if (*staddr) + g_assert ((current > *staddr) && (current < *staddr + *stsize)); #endif - pthread_attr_destroy (&attr); + pthread_attr_destroy (&attr); #endif - /* When running under emacs, sometimes staddr is not aligned to a page size */ - *staddr = (guint8*)((gssize)*staddr & ~(mono_pagesize () - 1)); + /* When running under emacs, sometimes staddr is not aligned to a page size */ + *staddr = (guint8*)((gssize)*staddr & ~(mono_pagesize () - 1)); } MonoThread * @@ -1051,16 +1058,8 @@ void ves_icall_System_Threading_Thread_Sleep_internal(gint32 ms) mono_thread_clr_state (thread, ThreadState_WaitSleepJoin); } -void ves_icall_System_Threading_Thread_SpinWait_internal (gint32 iterations) +void ves_icall_System_Threading_Thread_SpinWait_nop (void) { - gint32 i; - - for(i = 0; i < iterations; i++) { - /* We're busy waiting, but at least we can tell the - * scheduler to let someone else have a go... - */ - Sleep (0); - } } gint32 @@ -1274,8 +1273,9 @@ ves_icall_System_Threading_Thread_SetSerializedCurrentUICulture (MonoThread *thi MonoThread * mono_thread_current (void) { - THREAD_DEBUG (g_message ("%s: returning %p", __func__, GET_CURRENT_OBJECT ())); - return GET_CURRENT_OBJECT (); + MonoThread *res = GET_CURRENT_OBJECT () + THREAD_DEBUG (g_message ("%s: returning %p", __func__, res)); + return res; } gboolean ves_icall_System_Threading_Thread_Join_internal(MonoThread *this, @@ -1931,6 +1931,9 @@ void ves_icall_System_Threading_Thread_Interrupt_internal (MonoThread *this) gboolean throw = FALSE; ensure_synch_cs_set (this); + + if (this == mono_thread_current ()) + return; EnterCriticalSection (this->synch_cs); @@ -1952,6 +1955,8 @@ void mono_thread_current_check_pending_interrupt () MonoThread *thread = mono_thread_current (); gboolean throw = FALSE; + mono_debugger_check_interruption (); + ensure_synch_cs_set (thread); EnterCriticalSection (thread->synch_cs); @@ -2028,6 +2033,15 @@ static void signal_thread_state_change (MonoThread *thread) #else pthread_kill (thread->tid, mono_thread_get_abort_signal ()); #endif + + /* + * This will cause waits to be broken. + * It will also prevent the thread from entering a wait, so if the thread returns + * from the wait before it receives the abort signal, it will just spin in the wait + * functions in the io-layer until the signal handler calls QueueUserAPC which will + * make it return. + */ + wapi_interrupt_thread (thread->handle); #endif /* PLATFORM_WIN32 */ } @@ -2061,9 +2075,11 @@ ves_icall_System_Threading_Thread_Abort (MonoThread *thread, MonoObject *state) LeaveCriticalSection (thread->synch_cs); THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Abort requested for %p (%"G_GSIZE_FORMAT")", __func__, GetCurrentThreadId (), thread, (gsize)thread->tid)); - - /* Make sure the thread is awake */ - mono_thread_resume (thread); + + /* During shutdown, we can't wait for other threads */ + if (!shutting_down) + /* Make sure the thread is awake */ + mono_thread_resume (thread); signal_thread_state_change (thread); } @@ -3026,6 +3042,7 @@ mono_threads_abort_appdomain_threads (MonoDomain *domain, int timeout) { abort_appdomain_data user_data; guint32 start_time; + int orig_timeout = timeout; THREAD_DEBUG (g_message ("%s: starting abort", __func__)); @@ -3049,7 +3066,7 @@ mono_threads_abort_appdomain_threads (MonoDomain *domain, int timeout) timeout -= mono_msec_ticks () - start_time; start_time = mono_msec_ticks (); - if (timeout < 0) + if (orig_timeout != -1 && timeout < 0) return FALSE; } while (user_data.wait.num > 0); @@ -3453,6 +3470,10 @@ static MonoException* mono_thread_execute_interruption (MonoThread *thread) WaitForSingleObjectEx (GetCurrentThread(), 0, TRUE); InterlockedDecrement (&thread_interruption_requested); thread->interruption_requested = FALSE; +#ifndef PLATFORM_WIN32 + /* Clear the interrupted flag of the thread so it can wait again */ + wapi_clear_interruption (); +#endif } if ((thread->state & ThreadState_AbortRequested) != 0) { @@ -3506,6 +3527,7 @@ static MonoException* mono_thread_execute_interruption (MonoThread *thread) return NULL; } else if (thread->thread_interrupt_requested) { + thread->thread_interrupt_requested = FALSE; LeaveCriticalSection (thread->synch_cs); return(mono_get_exception_thread_interrupted ()); @@ -3524,7 +3546,8 @@ static MonoException* mono_thread_execute_interruption (MonoThread *thread) * the thread. If the result is an exception that needs to be throw, it is * provided as return value. */ -MonoException* mono_thread_request_interruption (gboolean running_managed) +MonoException* +mono_thread_request_interruption (gboolean running_managed) { MonoThread *thread = mono_thread_current (); @@ -3532,16 +3555,8 @@ MonoException* mono_thread_request_interruption (gboolean running_managed) if (thread == NULL) return NULL; - ensure_synch_cs_set (thread); - - /* FIXME: This is NOT signal safe */ - EnterCriticalSection (thread->synch_cs); - - if (thread->interruption_requested) { - LeaveCriticalSection (thread->synch_cs); - + if (InterlockedCompareExchange (&thread->interruption_requested, 1, 0) == 1) return NULL; - } if (!running_managed || is_running_protected_wrapper ()) { /* Can't stop while in unmanaged code. Increase the global interruption @@ -3549,9 +3564,6 @@ MonoException* mono_thread_request_interruption (gboolean running_managed) checked and the thread will be interrupted. */ InterlockedIncrement (&thread_interruption_requested); - thread->interruption_requested = TRUE; - - LeaveCriticalSection (thread->synch_cs); if (mono_thread_notify_pending_exc_fn && !running_managed) /* The JIT will notify the thread about the interruption */ @@ -3565,8 +3577,6 @@ MonoException* mono_thread_request_interruption (gboolean running_managed) return NULL; } else { - LeaveCriticalSection (thread->synch_cs); - return mono_thread_execute_interruption (thread); } } @@ -3590,6 +3600,8 @@ 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);