Merge pull request #347 from JamesB7/master
[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_self_suspend (MonoThreadInfo *info)
30 {
31         g_assert (0);
32 }
33
34 gboolean
35 mono_threads_core_suspend (MonoThreadInfo *info)
36 {
37         g_assert (0);
38 }
39
40 gboolean
41 mono_threads_core_resume (MonoThreadInfo *info)
42 {
43         g_assert (0);
44 }
45
46 void
47 mono_threads_platform_register (MonoThreadInfo *info)
48 {
49 }
50
51 void
52 mono_threads_platform_free (MonoThreadInfo *info)
53 {
54 }
55
56 typedef struct {
57         LPTHREAD_START_ROUTINE start_routine;
58         void *arg;
59         MonoSemType registered;
60         gboolean suspend;
61         HANDLE suspend_event;
62 } ThreadStartInfo;
63
64 static DWORD WINAPI
65 inner_start_thread (LPVOID arg)
66 {
67         ThreadStartInfo *start_info = arg;
68         void *t_arg = start_info->arg;
69         int post_result;
70         LPTHREAD_START_ROUTINE start_func = start_info->start_routine;
71         DWORD result;
72         gboolean suspend = start_info->suspend;
73         HANDLE suspend_event = start_info->suspend_event;
74
75         mono_thread_info_attach (&result);
76
77         post_result = MONO_SEM_POST (&(start_info->registered));
78         g_assert (!post_result);
79
80         if (suspend)
81         {
82                 WaitForSingleObject (suspend_event, INFINITE); /* caller will suspend the thread before setting the event. */
83                 CloseHandle (suspend_event);
84         }
85
86         result = start_func (t_arg);
87
88         g_assert (!mono_domain_get ());
89
90         return result;
91 }
92
93 HANDLE
94 mono_threads_CreateThread (LPSECURITY_ATTRIBUTES attributes, SIZE_T stack_size, LPTHREAD_START_ROUTINE start_routine,
95                 LPVOID arg, DWORD creation_flags, LPDWORD thread_id)
96 {
97         ThreadStartInfo *start_info;
98         HANDLE result;
99
100         start_info = g_malloc0 (sizeof (ThreadStartInfo));
101         if (!start_info)
102                 return NULL;
103         MONO_SEM_INIT (&(start_info->registered), 0);
104         start_info->arg = arg;
105         start_info->start_routine = start_routine;
106         start_info->suspend = creation_flags & CREATE_SUSPENDED;
107         creation_flags &= ~CREATE_SUSPENDED;
108         if (start_info->suspend)
109         {
110                 start_info->suspend_event = CreateEvent (NULL, TRUE, FALSE, NULL);
111                 if (!start_info->suspend_event)
112                         return NULL;
113         }
114
115         result = CreateThread (attributes, stack_size, inner_start_thread, start_info, creation_flags, thread_id);
116
117         if (result) {
118                 while (MONO_SEM_WAIT (&(start_info->registered)) != 0) {
119                         /*if (EINTR != errno) ABORT("sem_wait failed"); */
120                 }
121                 if (start_info->suspend)
122                 {
123                         g_assert (SuspendThread (result) != (DWORD)-1);
124                         SetEvent (start_info->suspend_event);
125                 }
126         }
127         else if (start_info->suspend)
128                 CloseHandle (start_info->suspend_event);
129         MONO_SEM_DESTROY (&(start_info->registered));
130         g_free (start_info);
131         return result;
132 }
133
134
135 MonoNativeThreadId
136 mono_native_thread_id_get (void)
137 {
138         return GetCurrentThreadId ();
139 }
140
141 gboolean
142 mono_native_thread_id_equals (MonoNativeThreadId id1, MonoNativeThreadId id2)
143 {
144         return id1 == id2;
145 }
146
147 gboolean
148 mono_native_thread_create (MonoNativeThreadId *tid, gpointer func, gpointer arg)
149 {
150         return CreateThread (NULL, 0, (func), (arg), 0, (tid)) != NULL;
151 }
152
153 #endif