[sgen] Basic Win32 support.
[mono.git] / mono / utils / mono-threads.h
1 /*
2  * mono-threads.h: Low-level threading
3  *
4  * Author:
5  *      Rodrigo Kumpera (kumpera@gmail.com)
6  *
7  * (C) 2011 Novell, Inc
8  */
9
10 #ifndef __MONO_THREADS_H__
11 #define __MONO_THREADS_H__
12
13 #include <mono/utils/mono-semaphore.h>
14 #include <mono/utils/mono-stack-unwinding.h>
15 #include <mono/utils/mono-linked-list-set.h>
16
17 /* FIXME used for CRITICAL_SECTION replace with mono-mutex  */
18 #include <mono/io-layer/io-layer.h>
19
20 #include <glib.h>
21
22 #ifdef HOST_WIN32
23
24 #include <windows.h>
25
26 typedef DWORD MonoNativeThreadId;
27 typedef HANDLE MonoNativeThreadHandle; /* unused */
28
29 typedef DWORD mono_native_thread_return_t;
30
31 #define mono_native_thread_id_get GetCurrentThreadId
32 #define mono_native_thread_id_equals(a,b) ((a) == ((b))
33
34 HANDLE mono_threads_CreateThread (LPSECURITY_ATTRIBUTES attributes, SIZE_T stack_size, LPTHREAD_START_ROUTINE start_routine,
35                 LPVOID arg, DWORD creation_flags, LPDWORD thread_id) MONO_INTERNAL;
36
37 #define mono_native_thread_create(id,func,arg)  (CreateThread (NULL, 0, (func), (arg), 0, (id)) != NULL)
38
39 #else
40
41 #include <pthread.h>
42
43 #if defined(__MACH__)
44 #include <mono/utils/mach-support.h>
45
46 typedef thread_port_t MonoNativeThreadHandle;
47
48 #else
49
50 #include <unistd.h>
51
52 typedef pid_t MonoNativeThreadHandle;
53
54 #endif /* defined(__MACH__) */
55
56 typedef pthread_t MonoNativeThreadId;
57
58 typedef void* mono_native_thread_return_t;
59
60 #define mono_native_thread_id_get pthread_self
61 #define mono_native_thread_id_equals(a,b) pthread_equal((a),(b))
62
63 #define mono_native_thread_create(tid,func,arg) (pthread_create ((tid), NULL, (func), (arg)) == 0)
64
65 #endif /* #ifdef HOST_WIN32 */
66
67 #ifndef THREAD_INFO_TYPE
68 #define THREAD_INFO_TYPE MonoThreadInfo
69 #endif
70
71 enum {
72         STATE_STARTING                  = 0x01,
73         STATE_RUNNING                   = 0x02,
74         STATE_SHUTTING_DOWN             = 0x03,
75         STATE_DEAD                              = 0x04,
76         RUN_STATE_MASK                  = 0x0F,
77
78         STATE_SUSPENDED                 = 0x10,
79         STATE_SELF_SUSPENDED    = 0x20,
80         SUSPEND_STATE_MASK              = 0xF0,
81 };
82
83 #define mono_thread_info_run_state(info) ((info)->thread_state & RUN_STATE_MASK)
84 #define mono_thread_info_suspend_state(info) ((info)->thread_state & SUSPEND_STATE_MASK)
85
86 typedef struct {
87         MonoLinkedListSetNode node;
88         guint32 small_id; /*Used by hazard pointers */
89         MonoNativeThreadHandle native_handle; /* Valid on mach and android */
90         int thread_state;
91
92         /* suspend machinery, fields protected by the suspend_lock */
93         CRITICAL_SECTION suspend_lock;
94         int suspend_count;
95
96         MonoSemType finish_resume_semaphore;
97         MonoSemType resume_semaphore; 
98
99         /* only needed by the posix backend */ 
100 #if (defined(_POSIX_VERSION) || defined(__native_client__)) && !defined (__MACH__)
101         MonoSemType suspend_semaphore;
102 #endif
103
104         /*In theory, only the posix backend needs this, but having it on mach/win32 simplifies things a lot.*/
105         MonoThreadUnwindState suspend_state;
106
107         /*async call machinery, thread MUST be suspended before accessing those fields*/
108         void (*async_target)(void*);
109         void *user_data;
110 } MonoThreadInfo;
111
112 typedef struct {
113         void* (*thread_register)(THREAD_INFO_TYPE *info, void *baseaddr);
114         /*
115         This callback is called after @info is removed from the thread list.
116         SMR remains functional as its small_id has not been reclaimed.
117         */
118         void (*thread_unregister)(THREAD_INFO_TYPE *info);
119         void (*thread_attach)(THREAD_INFO_TYPE *info);
120         gboolean (*mono_method_is_critical) (void *method);
121 #ifndef HOST_WIN32
122         int (*mono_gc_pthread_create) (pthread_t *new_thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);
123 #endif
124 } MonoThreadInfoCallbacks;
125
126 typedef struct {
127         void (*setup_async_callback) (MonoContext *ctx, void (*async_cb)(void *fun), gpointer user_data);
128         gboolean (*thread_state_init_from_sigctx) (MonoThreadUnwindState *state, void *sigctx);
129         gboolean (*thread_state_init_from_handle) (MonoThreadUnwindState *tctx, MonoNativeThreadId thread_id, MonoNativeThreadHandle thread_handle);
130 } MonoThreadInfoRuntimeCallbacks;
131
132 /*
133 Requires the world to be stoped
134 */
135 #define FOREACH_THREAD(thread) MONO_LLS_FOREACH (mono_thread_info_list_head (), thread)
136 #define END_FOREACH_THREAD MONO_LLS_END_FOREACH
137
138 /*
139 Snapshot iteration.
140 */
141 #define FOREACH_THREAD_SAFE(thread) MONO_LLS_FOREACH_SAFE (mono_thread_info_list_head (), thread)
142 #define END_FOREACH_THREAD_SAFE MONO_LLS_END_FOREACH_SAFE
143
144 #define mono_thread_info_get_tid(info) ((MonoNativeThreadId)((MonoThreadInfo*)info)->node.key)
145 #define mono_thread_info_set_tid(info, val) do { ((MonoThreadInfo*)(info))->node.key = (uintptr_t)(val); } while (0)
146
147 /*
148  * @thread_info_size is sizeof (GcThreadInfo), a struct the GC defines to make it possible to have
149  * a single block with info from both camps. 
150  */
151 void
152 mono_threads_init (MonoThreadInfoCallbacks *callbacks, size_t thread_info_size) MONO_INTERNAL;
153
154 void
155 mono_threads_runtime_init (MonoThreadInfoRuntimeCallbacks *callbacks) MONO_INTERNAL;
156
157 MonoThreadInfoCallbacks *
158 mono_threads_get_callbacks (void) MONO_INTERNAL;
159
160 MonoThreadInfoRuntimeCallbacks *
161 mono_threads_get_runtime_callbacks (void) MONO_INTERNAL;
162
163 int
164 mono_thread_info_register_small_id (void) MONO_INTERNAL;
165
166 THREAD_INFO_TYPE *
167 mono_thread_info_attach (void *baseptr) MONO_INTERNAL;
168
169 void
170 mono_thread_info_dettach (void) MONO_INTERNAL;
171
172 THREAD_INFO_TYPE *
173 mono_thread_info_current (void) MONO_INTERNAL;
174
175 int
176 mono_thread_info_get_small_id (void) MONO_INTERNAL;
177
178 MonoLinkedListSet*
179 mono_thread_info_list_head (void) MONO_INTERNAL;
180
181 MonoThreadInfo*
182 mono_thread_info_lookup (MonoNativeThreadId id) MONO_INTERNAL;
183
184 MonoThreadInfo*
185 mono_thread_info_safe_suspend_sync (MonoNativeThreadId tid, gboolean interrupt_kernel) MONO_INTERNAL;
186
187 gboolean
188 mono_thread_info_resume (MonoNativeThreadId tid) MONO_INTERNAL;
189
190 void
191 mono_thread_info_self_suspend (void) MONO_INTERNAL;
192
193 gboolean
194 mono_thread_info_new_interrupt_enabled (void) MONO_INTERNAL;
195
196 void
197 mono_thread_info_setup_async_call (MonoThreadInfo *info, void (*target_func)(void*), void *user_data) MONO_INTERNAL;
198
199 void
200 mono_thread_info_suspend_lock (void) MONO_INTERNAL;
201
202 void
203 mono_thread_info_suspend_unlock (void) MONO_INTERNAL;
204
205 void
206 mono_threads_unregister_current_thread (THREAD_INFO_TYPE *info) MONO_INTERNAL;
207
208 void
209 mono_thread_info_disable_new_interrupt (gboolean disable) MONO_INTERNAL;
210
211
212 #if !defined(HOST_WIN32)
213
214 int
215 mono_threads_pthread_create (pthread_t *new_thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg) MONO_INTERNAL;
216
217 #if !defined(__MACH__)
218 /*Use this instead of pthread_kill */
219 int
220 mono_threads_pthread_kill (THREAD_INFO_TYPE *info, int signum) MONO_INTERNAL;
221 #endif
222
223 #endif /* !defined(HOST_WIN32) */
224
225 /* Plartform specific functions DON'T use them */
226 void mono_threads_init_platform (void) MONO_INTERNAL; //ok
227 gboolean mono_threads_core_suspend (MonoThreadInfo *info) MONO_INTERNAL;
228 gboolean mono_threads_core_resume (MonoThreadInfo *info) MONO_INTERNAL;
229 void mono_threads_platform_register (MonoThreadInfo *info) MONO_INTERNAL; //ok
230 void mono_threads_platform_free (MonoThreadInfo *info) MONO_INTERNAL;
231 void mono_threads_core_interrupt (MonoThreadInfo *info) MONO_INTERNAL;
232
233 #endif /* __MONO_THREADS_H__ */