2 * mono-threads-windows.c: Low-level threading, windows version
5 * Rodrigo Kumpera (kumpera@gmail.com)
12 #if defined(HOST_WIN32)
14 #include <mono/utils/mono-threads.h>
18 mono_threads_init_platform (void)
23 mono_threads_core_interrupt (MonoThreadInfo *info)
29 mono_threads_core_abort_syscall (MonoThreadInfo *info)
34 mono_threads_core_needs_abort_syscall (void)
40 mono_threads_core_self_suspend (MonoThreadInfo *info)
46 mono_threads_core_suspend (MonoThreadInfo *info)
52 mono_threads_core_resume (MonoThreadInfo *info)
58 mono_threads_platform_register (MonoThreadInfo *info)
63 mono_threads_platform_free (MonoThreadInfo *info)
68 LPTHREAD_START_ROUTINE start_routine;
70 MonoSemType registered;
76 inner_start_thread (LPVOID arg)
78 ThreadStartInfo *start_info = arg;
79 void *t_arg = start_info->arg;
81 LPTHREAD_START_ROUTINE start_func = start_info->start_routine;
83 gboolean suspend = start_info->suspend;
84 HANDLE suspend_event = start_info->suspend_event;
87 info = mono_thread_info_attach (&result);
88 info->runtime_thread = TRUE;
89 info->create_suspended = suspend;
91 post_result = MONO_SEM_POST (&(start_info->registered));
92 g_assert (!post_result);
95 WaitForSingleObject (suspend_event, INFINITE); /* caller will suspend the thread before setting the event. */
96 CloseHandle (suspend_event);
99 result = start_func (t_arg);
101 g_assert (!mono_domain_get ());
103 mono_thread_info_detach ();
109 mono_threads_core_create_thread (LPTHREAD_START_ROUTINE start_routine, gpointer arg, guint32 stack_size, guint32 creation_flags, MonoNativeThreadId *out_tid)
111 ThreadStartInfo *start_info;
115 start_info = g_malloc0 (sizeof (ThreadStartInfo));
118 MONO_SEM_INIT (&(start_info->registered), 0);
119 start_info->arg = arg;
120 start_info->start_routine = start_routine;
121 start_info->suspend = creation_flags & CREATE_SUSPENDED;
122 creation_flags &= ~CREATE_SUSPENDED;
123 if (start_info->suspend) {
124 start_info->suspend_event = CreateEvent (NULL, TRUE, FALSE, NULL);
125 if (!start_info->suspend_event)
129 result = CreateThread (NULL, stack_size, inner_start_thread, start_info, creation_flags, &thread_id);
131 while (MONO_SEM_WAIT (&(start_info->registered)) != 0) {
132 /*if (EINTR != errno) ABORT("sem_wait failed"); */
134 if (start_info->suspend) {
135 g_assert (SuspendThread (result) != (DWORD)-1);
136 SetEvent (start_info->suspend_event);
138 } else if (start_info->suspend) {
139 CloseHandle (start_info->suspend_event);
142 *out_tid = thread_id;
143 MONO_SEM_DESTROY (&(start_info->registered));
150 mono_native_thread_id_get (void)
152 return GetCurrentThreadId ();
156 mono_native_thread_id_equals (MonoNativeThreadId id1, MonoNativeThreadId id2)
162 mono_native_thread_create (MonoNativeThreadId *tid, gpointer func, gpointer arg)
164 return CreateThread (NULL, 0, (func), (arg), 0, (tid)) != NULL;
168 mono_threads_core_resume_created (MonoThreadInfo *info, MonoNativeThreadId tid)
172 handle = OpenThread (THREAD_ALL_ACCESS, TRUE, tid);
174 ResumeThread (handle);
175 CloseHandle (handle);
178 #if HAVE_DECL___READFSDWORD==0
179 static __inline__ __attribute__((always_inline))
181 __readfsdword (unsigned long offset)
184 // __asm__("movl %%fs:%a[offset], %k[value]" : [value] "=q" (value) : [offset] "irm" (offset));
185 __asm__ volatile ("movl %%fs:%1,%0"
186 : "=r" (value) ,"=m" ((*(volatile long *) offset)));
192 mono_threads_core_get_stack_bounds (guint8 **staddr, size_t *stsize)
196 NT_TIB* tib = (NT_TIB*)NtCurrentTeb();
197 guint8 *stackTop = (guint8*)tib->StackBase;
198 guint8 *stackBottom = (guint8*)tib->StackLimit;
200 /* http://en.wikipedia.org/wiki/Win32_Thread_Information_Block */
201 void* tib = (void*)__readfsdword(0x18);
202 guint8 *stackTop = (guint8*)*(int*)((char*)tib + 4);
203 guint8 *stackBottom = (guint8*)*(int*)((char*)tib + 8);
206 *staddr = stackBottom;
207 *stsize = stackTop - stackBottom;
211 mono_threads_core_yield (void)
213 return SwitchToThread ();
217 mono_threads_core_exit (int exit_code)
219 ExitThread (exit_code);
223 mono_threads_core_unregister (MonoThreadInfo *info)
228 mono_threads_core_open_handle (void)
230 HANDLE thread_handle;
232 thread_handle = GetCurrentThread ();
233 g_assert (thread_handle);
236 * The handle returned by GetCurrentThread () is a pseudo handle, so it can't be used to
237 * refer to the thread from other threads for things like aborting.
239 DuplicateHandle (GetCurrentProcess (), thread_handle, GetCurrentProcess (), &thread_handle,
240 THREAD_ALL_ACCESS, TRUE, 0);
242 return thread_handle;