X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Futils%2Fmono-threads-windows.c;h=563d210e8ed5cfe9ef657e7aba24d77d0f0429cf;hb=HEAD;hp=f66e6936b6dc1df123ab5060db34eb65a74ef86f;hpb=66fd6fd24dd58ff1432279df13a385b0a78263e2;p=mono.git diff --git a/mono/utils/mono-threads-windows.c b/mono/utils/mono-threads-windows.c index f66e6936b6d..563d210e8ed 100644 --- a/mono/utils/mono-threads-windows.c +++ b/mono/utils/mono-threads-windows.c @@ -1,5 +1,6 @@ -/* - * mono-threads-windows.c: Low-level threading, windows version +/** + * \file + * Low-level threading, windows version * * Author: * Rodrigo Kumpera (kumpera@gmail.com) @@ -12,19 +13,15 @@ #if defined(USE_WINDOWS_BACKEND) #include +#include +#include #include - void mono_threads_suspend_init (void) { } -static void CALLBACK -interrupt_apc (ULONG_PTR param) -{ -} - gboolean mono_threads_suspend_begin_async_suspend (MonoThreadInfo *info, gboolean interrupt_kernel) { @@ -55,15 +52,14 @@ mono_threads_suspend_begin_async_suspend (MonoThreadInfo *info, gboolean interru info->suspend_can_continue = mono_threads_get_runtime_callbacks ()->thread_state_init_from_handle (&info->thread_saved_state [ASYNC_SUSPEND_STATE_INDEX], info); THREADS_SUSPEND_DEBUG ("thread state %p -> %d\n", (void*)id, res); if (info->suspend_can_continue) { - //FIXME do we need to QueueUserAPC on this case? if (interrupt_kernel) - QueueUserAPC ((PAPCFUNC)interrupt_apc, handle, (ULONG_PTR)NULL); + mono_win32_interrupt_wait (info, handle, id); } else { THREADS_SUSPEND_DEBUG ("FAILSAFE RESUME/2 %p -> %d\n", (void*)info->native_handle, 0); } CloseHandle (handle); - return info->suspend_can_continue; + return TRUE; } gboolean @@ -72,6 +68,22 @@ mono_threads_suspend_check_suspend_result (MonoThreadInfo *info) return info->suspend_can_continue; } + + +void +mono_threads_suspend_abort_syscall (MonoThreadInfo *info) +{ + DWORD id = mono_thread_info_get_tid (info); + HANDLE handle; + + handle = OpenThread (THREAD_ALL_ACCESS, FALSE, id); + g_assert (handle); + + mono_win32_abort_wait (info, handle, id); + + CloseHandle (handle); +} + gboolean mono_threads_suspend_begin_async_resume (MonoThreadInfo *info) { @@ -128,111 +140,63 @@ mono_threads_suspend_free (MonoThreadInfo *info) { } -#endif - -#if defined (HOST_WIN32) - void -mono_threads_platform_register (MonoThreadInfo *info) +mono_threads_suspend_init_signals (void) { - HANDLE thread_handle; - - thread_handle = GetCurrentThread (); - g_assert (thread_handle); - - /* The handle returned by GetCurrentThread () is a pseudo handle, so it can't - * be used to refer to the thread from other threads for things like aborting. */ - DuplicateHandle (GetCurrentProcess (), thread_handle, GetCurrentProcess (), &thread_handle, THREAD_ALL_ACCESS, TRUE, 0); - - g_assert (!info->handle); - info->handle = thread_handle; } -typedef struct { - LPTHREAD_START_ROUTINE start_routine; - void *arg; - gint32 priority; - MonoCoopSem registered; - gboolean suspend; - HANDLE suspend_event; - HANDLE handle; -} ThreadStartInfo; - -static DWORD WINAPI -inner_start_thread (LPVOID arg) +gint +mono_threads_suspend_search_alternative_signal (void) { - ThreadStartInfo *start_info = arg; - void *t_arg = start_info->arg; - LPTHREAD_START_ROUTINE start_func = start_info->start_routine; - DWORD result; - gboolean suspend = start_info->suspend; - HANDLE suspend_event = start_info->suspend_event; - MonoThreadInfo *info; - - info = mono_thread_info_attach (&result); - info->runtime_thread = TRUE; - info->create_suspended = suspend; - - start_info->handle = info->handle; - - mono_threads_platform_set_priority(info, start_info->priority); + g_assert_not_reached (); +} - mono_coop_sem_post (&(start_info->registered)); +gint +mono_threads_suspend_get_suspend_signal (void) +{ + return -1; +} - if (suspend) { - WaitForSingleObject (suspend_event, INFINITE); /* caller will suspend the thread before setting the event. */ - CloseHandle (suspend_event); - } +gint +mono_threads_suspend_get_restart_signal (void) +{ + return -1; +} - result = start_func (t_arg); +gint +mono_threads_suspend_get_abort_signal (void) +{ + return -1; +} - mono_thread_info_detach (); +#endif - return result; -} +#if defined (HOST_WIN32) -HANDLE -mono_threads_platform_create_thread (MonoThreadStart start_routine, gpointer arg, MonoThreadParm *tp, MonoNativeThreadId *out_tid) +gboolean +mono_thread_platform_create_thread (MonoThreadStart thread_fn, gpointer thread_data, gsize* const stack_size, MonoNativeThreadId *tid) { - ThreadStartInfo start_info; HANDLE result; DWORD thread_id; - guint32 creation_flags = tp->creation_flags; - int res; - - memset (&start_info, 0, sizeof (start_info)); - mono_coop_sem_init (&(start_info.registered), 0); - start_info.arg = arg; - start_info.start_routine = start_routine; - start_info.suspend = creation_flags & CREATE_SUSPENDED; - start_info.priority = tp->priority; - creation_flags &= ~CREATE_SUSPENDED; - if (start_info.suspend) { - start_info.suspend_event = CreateEvent (NULL, TRUE, FALSE, NULL); - if (!start_info.suspend_event) - return NULL; - } - result = CreateThread (NULL, tp->stack_size, inner_start_thread, &start_info, creation_flags, &thread_id); - if (result) { - res = mono_coop_sem_wait (&(start_info.registered), MONO_SEM_FLAGS_NONE); - g_assert (res != -1); + result = CreateThread (NULL, stack_size ? *stack_size : 0, (LPTHREAD_START_ROUTINE) thread_fn, thread_data, 0, &thread_id); + if (!result) + return FALSE; - /* A new handle has been opened when attaching - * the thread, so we don't need this one */ - CloseHandle (result); + /* A new handle is open when attaching + * the thread, so we don't need this one */ + CloseHandle (result); - if (start_info.suspend) { - g_assert (SuspendThread (start_info.handle) != (DWORD)-1); - SetEvent (start_info.suspend_event); - } - } else if (start_info.suspend) { - CloseHandle (start_info.suspend_event); + if (tid) + *tid = thread_id; + + if (stack_size) { + // TOOD: Use VirtualQuery to get correct value + // http://stackoverflow.com/questions/2480095/thread-stack-size-on-windows-visual-c + *stack_size = 2 * 1024 * 1024; } - if (out_tid) - *out_tid = thread_id; - mono_coop_sem_destroy (&(start_info.registered)); - return start_info.handle; + + return TRUE; } @@ -254,15 +218,26 @@ mono_native_thread_create (MonoNativeThreadId *tid, gpointer func, gpointer arg) return CreateThread (NULL, 0, (func), (arg), 0, (tid)) != NULL; } -void -mono_threads_platform_resume_created (MonoThreadInfo *info, MonoNativeThreadId tid) +gboolean +mono_native_thread_join_handle (HANDLE thread_handle, gboolean close_handle) +{ + DWORD res = WaitForSingleObject (thread_handle, INFINITE); + + if (close_handle) + CloseHandle (thread_handle); + + return res != WAIT_FAILED; +} + +gboolean +mono_native_thread_join (MonoNativeThreadId tid) { HANDLE handle; - handle = OpenThread (THREAD_ALL_ACCESS, TRUE, tid); - g_assert (handle); - ResumeThread (handle); - CloseHandle (handle); + if (!(handle = OpenThread (SYNCHRONIZE, TRUE, tid))) + return FALSE; + + return mono_native_thread_join_handle (handle, TRUE); } #if HAVE_DECL___READFSDWORD==0 @@ -305,21 +280,66 @@ mono_threads_platform_get_stack_bounds (guint8 **staddr, size_t *stsize) } +#if SIZEOF_VOID_P == 4 && G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) +typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL); +static gboolean is_wow64 = FALSE; +#endif + +/* We do this at init time to avoid potential races with module opening */ +void +mono_threads_platform_init (void) +{ +#if SIZEOF_VOID_P == 4 && G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) + LPFN_ISWOW64PROCESS is_wow64_func = (LPFN_ISWOW64PROCESS) GetProcAddress (GetModuleHandle (TEXT ("kernel32")), "IsWow64Process"); + if (is_wow64_func) + is_wow64_func (GetCurrentProcess (), &is_wow64); +#endif +} + +/* + * When running x86 process under x64 system syscalls are done through WoW64. This + * needs to do a transition from x86 mode to x64 so it can syscall into the x64 system. + * Apparently this transition invalidates the ESP that we would get from calling + * GetThreadContext, so we would fail to scan parts of the thread stack. We attempt + * to query whether the thread is in such a transition so we try to restart it later. + * We check CONTEXT_EXCEPTION_ACTIVE for this, which is highly undocumented. + */ gboolean -mono_threads_platform_yield (void) +mono_threads_platform_in_critical_region (MonoNativeThreadId tid) { - return SwitchToThread (); + gboolean ret = FALSE; +#if SIZEOF_VOID_P == 4 && G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) +/* FIXME On cygwin these are not defined */ +#if defined(CONTEXT_EXCEPTION_REQUEST) && defined(CONTEXT_EXCEPTION_REPORTING) && defined(CONTEXT_EXCEPTION_ACTIVE) + if (is_wow64) { + HANDLE handle = OpenThread (THREAD_ALL_ACCESS, FALSE, tid); + if (handle) { + CONTEXT context; + ZeroMemory (&context, sizeof (CONTEXT)); + context.ContextFlags = CONTEXT_EXCEPTION_REQUEST; + if (GetThreadContext (handle, &context)) { + if ((context.ContextFlags & CONTEXT_EXCEPTION_REPORTING) && + (context.ContextFlags & CONTEXT_EXCEPTION_ACTIVE)) + ret = TRUE; + } + CloseHandle (handle); + } + } +#endif +#endif + return ret; } -void -mono_threads_platform_exit (int exit_code) +gboolean +mono_threads_platform_yield (void) { - ExitThread (exit_code); + return SwitchToThread (); } void -mono_threads_platform_unregister (MonoThreadInfo *info) +mono_threads_platform_exit (gsize exit_code) { + ExitThread (exit_code); } int @@ -329,12 +349,6 @@ mono_threads_get_max_stack_size (void) return INT_MAX; } -HANDLE -mono_threads_platform_open_thread_handle (HANDLE handle, MonoNativeThreadId tid) -{ - return OpenThread (THREAD_ALL_ACCESS, TRUE, tid); -} - #if defined(_MSC_VER) const DWORD MS_VC_EXCEPTION=0x406D1388; #pragma pack(push,8) @@ -367,46 +381,4 @@ mono_native_thread_set_name (MonoNativeThreadId tid, const char *name) #endif } -void -mono_threads_platform_set_exited (MonoThreadInfo *info) -{ -} - -void -mono_threads_platform_describe (MonoThreadInfo *info, GString *text) -{ - /* TODO */ -} - -void -mono_threads_platform_own_mutex (MonoThreadInfo *info, gpointer mutex_handle) -{ - g_assert_not_reached (); -} - -void -mono_threads_platform_disown_mutex (MonoThreadInfo *info, gpointer mutex_handle) -{ - g_assert_not_reached (); -} - -MonoThreadPriority -mono_threads_platform_get_priority (MonoThreadInfo *info) -{ - g_assert (info->handle); - return GetThreadPriority (info->handle) + 2; -} - -gboolean -mono_threads_platform_set_priority (MonoThreadInfo *info, MonoThreadPriority priority) -{ - g_assert (info->handle); - return SetThreadPriority (info->handle, priority - 2); -} - -void -mono_threads_platform_init (void) -{ -} - #endif