Merge pull request #439 from mono-soc-2012/garyb/iconfix
[mono.git] / mono / utils / mono-threads-windows.c
1 /*
2  * mono-threads-windows.c: Low-level threading, windows version
3  *
4  * Author:
5  *      Rodrigo Kumpera (kumpera@gmail.com)
6  *
7  * (C) 2011 Novell, Inc
8  */
9
10 #include "config.h"
11
12 #if defined(HOST_WIN32)
13
14 #include <mono/utils/mono-threads.h>
15
16
17 void
18 mono_threads_init_platform (void)
19 {
20 }
21
22 void
23 mono_threads_core_interrupt (MonoThreadInfo *info)
24 {
25         g_assert (0);
26 }
27
28 void
29 mono_threads_core_abort_syscall (MonoThreadInfo *info)
30 {
31 }
32
33 gboolean
34 mono_threads_core_needs_abort_syscall (void)
35 {
36         return FALSE;
37 }
38
39 void
40 mono_threads_core_self_suspend (MonoThreadInfo *info)
41 {
42         g_assert (0);
43 }
44
45 gboolean
46 mono_threads_core_suspend (MonoThreadInfo *info)
47 {
48         g_assert (0);
49 }
50
51 gboolean
52 mono_threads_core_resume (MonoThreadInfo *info)
53 {
54         g_assert (0);
55 }
56
57 void
58 mono_threads_platform_register (MonoThreadInfo *info)
59 {
60 }
61
62 void
63 mono_threads_platform_free (MonoThreadInfo *info)
64 {
65 }
66
67 typedef struct {
68         LPTHREAD_START_ROUTINE start_routine;
69         void *arg;
70         MonoSemType registered;
71         gboolean suspend;
72         HANDLE suspend_event;
73 } ThreadStartInfo;
74
75 static DWORD WINAPI
76 inner_start_thread (LPVOID arg)
77 {
78         ThreadStartInfo *start_info = arg;
79         void *t_arg = start_info->arg;
80         int post_result;
81         LPTHREAD_START_ROUTINE start_func = start_info->start_routine;
82         DWORD result;
83         gboolean suspend = start_info->suspend;
84         HANDLE suspend_event = start_info->suspend_event;
85
86         mono_thread_info_attach (&result);
87
88         post_result = MONO_SEM_POST (&(start_info->registered));
89         g_assert (!post_result);
90
91         if (suspend)
92         {
93                 WaitForSingleObject (suspend_event, INFINITE); /* caller will suspend the thread before setting the event. */
94                 CloseHandle (suspend_event);
95         }
96
97         result = start_func (t_arg);
98
99         g_assert (!mono_domain_get ());
100
101         return result;
102 }
103
104 HANDLE
105 mono_threads_CreateThread (LPSECURITY_ATTRIBUTES attributes, SIZE_T stack_size, LPTHREAD_START_ROUTINE start_routine,
106                 LPVOID arg, DWORD creation_flags, LPDWORD thread_id)
107 {
108         ThreadStartInfo *start_info;
109         HANDLE result;
110
111         start_info = g_malloc0 (sizeof (ThreadStartInfo));
112         if (!start_info)
113                 return NULL;
114         MONO_SEM_INIT (&(start_info->registered), 0);
115         start_info->arg = arg;
116         start_info->start_routine = start_routine;
117         start_info->suspend = creation_flags & CREATE_SUSPENDED;
118         creation_flags &= ~CREATE_SUSPENDED;
119         if (start_info->suspend)
120         {
121                 start_info->suspend_event = CreateEvent (NULL, TRUE, FALSE, NULL);
122                 if (!start_info->suspend_event)
123                         return NULL;
124         }
125
126         result = CreateThread (attributes, stack_size, inner_start_thread, start_info, creation_flags, thread_id);
127
128         if (result) {
129                 while (MONO_SEM_WAIT (&(start_info->registered)) != 0) {
130                         /*if (EINTR != errno) ABORT("sem_wait failed"); */
131                 }
132                 if (start_info->suspend)
133                 {
134                         g_assert (SuspendThread (result) != (DWORD)-1);
135                         SetEvent (start_info->suspend_event);
136                 }
137         }
138         else if (start_info->suspend)
139                 CloseHandle (start_info->suspend_event);
140         MONO_SEM_DESTROY (&(start_info->registered));
141         g_free (start_info);
142         return result;
143 }
144
145
146 MonoNativeThreadId
147 mono_native_thread_id_get (void)
148 {
149         return GetCurrentThreadId ();
150 }
151
152 gboolean
153 mono_native_thread_id_equals (MonoNativeThreadId id1, MonoNativeThreadId id2)
154 {
155         return id1 == id2;
156 }
157
158 gboolean
159 mono_native_thread_create (MonoNativeThreadId *tid, gpointer func, gpointer arg)
160 {
161         return CreateThread (NULL, 0, (func), (arg), 0, (tid)) != NULL;
162 }
163
164 #endif