Reverse previous changes
[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 #else
32
33 #include <pthread.h>
34
35 #if defined(__MACH__)
36 #include <mono/utils/mach-support.h>
37
38 typedef thread_port_t MonoNativeThreadHandle;
39
40 #else
41
42 #include <unistd.h>
43
44 typedef pid_t MonoNativeThreadHandle;
45
46 #endif /* defined(__MACH__) */
47
48 typedef pthread_t MonoNativeThreadId;
49
50 typedef void* mono_native_thread_return_t;
51
52 #endif /* #ifdef HOST_WIN32 */
53
54 /*
55 THREAD_INFO_TYPE is a way to make the mono-threads module parametric - or sort of.
56 The GC using mono-threads might extend the MonoThreadInfo struct to add its own
57 data, this avoid a pointer indirection on what is on a lot of hot paths.
58
59 But extending MonoThreadInfo has de disavantage that all functions here return type
60 would require a cast, something like the following:
61
62 typedef struct {
63         MonoThreadInfo info;
64         int stuff;
65 }  MyThreadInfo;
66
67 ...
68 ((MyThreadInfo*)mono_thread_info_current ())->stuff = 1;
69
70 While porting sgen to use mono-threads, the number of casts required was too much and
71 code ended up looking horrible. So we use this cute little hack. The idea is that
72 whomever is including this header can set the expected type to be used by functions here
73 and reduce the number of casts drastically.
74
75 */
76 #ifndef THREAD_INFO_TYPE
77 #define THREAD_INFO_TYPE MonoThreadInfo
78 #endif
79
80 enum {
81         STATE_STARTING                  = 0x01,
82         STATE_RUNNING                   = 0x02,
83         STATE_SHUTTING_DOWN             = 0x03,
84         STATE_DEAD                              = 0x04,
85         RUN_STATE_MASK                  = 0x0F,
86
87         STATE_SUSPENDED                 = 0x10,
88         STATE_SELF_SUSPENDED    = 0x20,
89         SUSPEND_STATE_MASK              = 0xF0,
90 };
91
92 #define mono_thread_info_run_state(info) ((info)->thread_state & RUN_STATE_MASK)
93 #define mono_thread_info_suspend_state(info) ((info)->thread_state & SUSPEND_STATE_MASK)
94
95 typedef struct {
96         MonoLinkedListSetNode node;
97         guint32 small_id; /*Used by hazard pointers */
98         MonoNativeThreadHandle native_handle; /* Valid on mach and android */
99         int thread_state;
100
101         /* suspend machinery, fields protected by the suspend_lock */
102         CRITICAL_SECTION suspend_lock;
103         int suspend_count;
104
105         MonoSemType finish_resume_semaphore;
106         MonoSemType resume_semaphore; 
107
108         /* only needed by the posix backend */ 
109 #if (defined(_POSIX_VERSION) || defined(__native_client__)) && !defined (__MACH__)
110         MonoSemType suspend_semaphore;
111         gboolean syscall_break_signal;
112         gboolean suspend_can_continue;
113 #endif
114
115         /*In theory, only the posix backend needs this, but having it on mach/win32 simplifies things a lot.*/
116         MonoThreadUnwindState suspend_state;
117
118         /*async call machinery, thread MUST be suspended before accessing those fields*/
119         void (*async_target)(void*);
120         void *user_data;
121 } MonoThreadInfo;
122
123 typedef struct {
124         void* (*thread_register)(THREAD_INFO_TYPE *info, void *baseaddr);
125         /*
126         This callback is called after @info is removed from the thread list.
127         SMR remains functional as its small_id has not been reclaimed.
128         */
129         void (*thread_unregister)(THREAD_INFO_TYPE *info);
130         void (*thread_attach)(THREAD_INFO_TYPE *info);
131         gboolean (*mono_method_is_critical) (void *method);
132 #ifndef HOST_WIN32
133         int (*mono_gc_pthread_create) (pthread_t *new_thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);
134 #endif
135 } MonoThreadInfoCallbacks;
136
137 typedef struct {
138         void (*setup_async_callback) (MonoContext *ctx, void (*async_cb)(void *fun), gpointer user_data);
139         gboolean (*thread_state_init_from_sigctx) (MonoThreadUnwindState *state, void *sigctx);
140         gboolean (*thread_state_init_from_handle) (MonoThreadUnwindState *tctx, MonoNativeThreadId thread_id, MonoNativeThreadHandle thread_handle);
141 } MonoThreadInfoRuntimeCallbacks;
142
143 /*
144 Requires the world to be stoped
145 */
146 #define FOREACH_THREAD(thread) MONO_LLS_FOREACH (mono_thread_info_list_head (), thread, SgenThreadInfo*)
147 #define END_FOREACH_THREAD MONO_LLS_END_FOREACH
148
149 /*
150 Snapshot iteration.
151 */
152 #define FOREACH_THREAD_SAFE(thread) MONO_LLS_FOREACH_SAFE (mono_thread_info_list_head (), thread, SgenThreadInfo*)
153 #define END_FOREACH_THREAD_SAFE MONO_LLS_END_FOREACH_SAFE
154
155 #define mono_thread_info_get_tid(info) ((MonoNativeThreadId)((MonoThreadInfo*)info)->node.key)
156 #define mono_thread_info_set_tid(info, val) do { ((MonoThreadInfo*)(info))->node.key = (uintptr_t)(val); } while (0)
157
158 /*
159  * @thread_info_size is sizeof (GcThreadInfo), a struct the GC defines to make it possible to have
160  * a single block with info from both camps. 
161  */
162 void
163 mono_threads_init (MonoThreadInfoCallbacks *callbacks, size_t thread_info_size) MONO_INTERNAL;
164
165 void
166 mono_threads_runtime_init (MonoThreadInfoRuntimeCallbacks *callbacks) MONO_INTERNAL;
167
168 MonoThreadInfoCallbacks *
169 mono_threads_get_callbacks (void) MONO_INTERNAL;
170
171 MonoThreadInfoRuntimeCallbacks *
172 mono_threads_get_runtime_callbacks (void) MONO_INTERNAL;
173
174 int
175 mono_thread_info_register_small_id (void) MONO_INTERNAL;
176
177 THREAD_INFO_TYPE *
178 mono_thread_info_attach (void *baseptr) MONO_INTERNAL;
179
180 void
181 mono_thread_info_dettach (void) MONO_INTERNAL;
182
183 THREAD_INFO_TYPE *
184 mono_thread_info_current (void) MONO_INTERNAL;
185
186 int
187 mono_thread_info_get_small_id (void) MONO_INTERNAL;
188
189 MonoLinkedListSet*
190 mono_thread_info_list_head (void) MONO_INTERNAL;
191
192 MonoThreadInfo*
193 mono_thread_info_lookup (MonoNativeThreadId id) MONO_INTERNAL;
194
195 MonoThreadInfo*
196 mono_thread_info_safe_suspend_sync (MonoNativeThreadId tid, gboolean interrupt_kernel) MONO_INTERNAL;
197
198 gboolean
199 mono_thread_info_resume (MonoNativeThreadId tid) MONO_INTERNAL;
200
201 void
202 mono_thread_info_self_suspend (void) MONO_INTERNAL;
203
204 gboolean
205 mono_thread_info_new_interrupt_enabled (void) MONO_INTERNAL;
206
207 void
208 mono_thread_info_setup_async_call (MonoThreadInfo *info, void (*target_func)(void*), void *user_data) MONO_INTERNAL;
209
210 void
211 mono_thread_info_suspend_lock (void) MONO_INTERNAL;
212
213 void
214 mono_thread_info_suspend_unlock (void) MONO_INTERNAL;
215
216 void
217 mono_threads_unregister_current_thread (THREAD_INFO_TYPE *info) MONO_INTERNAL;
218
219 void
220 mono_thread_info_disable_new_interrupt (gboolean disable) MONO_INTERNAL;
221
222 void
223 mono_thread_info_abort_socket_syscall_for_close (MonoNativeThreadId tid) MONO_INTERNAL;
224
225 #if !defined(HOST_WIN32)
226
227 int
228 mono_threads_pthread_create (pthread_t *new_thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg) MONO_INTERNAL;
229
230 #if !defined(__MACH__)
231 /*Use this instead of pthread_kill */
232 int
233 mono_threads_pthread_kill (THREAD_INFO_TYPE *info, int signum) MONO_INTERNAL;
234 #endif
235
236 #else  /* !defined(HOST_WIN32) */
237
238 HANDLE
239         mono_threads_CreateThread (LPSECURITY_ATTRIBUTES attributes, SIZE_T stack_size, LPTHREAD_START_ROUTINE start_routine, LPVOID arg, DWORD creation_flags, LPDWORD thread_id);
240
241
242 #endif /* !defined(HOST_WIN32) */
243
244 /* Plartform specific functions DON'T use them */
245 void mono_threads_init_platform (void) MONO_INTERNAL; //ok
246 gboolean mono_threads_core_suspend (MonoThreadInfo *info) MONO_INTERNAL;
247 gboolean mono_threads_core_resume (MonoThreadInfo *info) MONO_INTERNAL;
248 void mono_threads_platform_register (MonoThreadInfo *info) MONO_INTERNAL; //ok
249 void mono_threads_platform_free (MonoThreadInfo *info) MONO_INTERNAL;
250 void mono_threads_core_interrupt (MonoThreadInfo *info) MONO_INTERNAL;
251 void mono_threads_core_abort_syscall (MonoThreadInfo *info) MONO_INTERNAL;
252 gboolean mono_threads_core_needs_abort_syscall (void) MONO_INTERNAL;
253
254 MonoNativeThreadId mono_native_thread_id_get (void) MONO_INTERNAL;
255
256 gboolean mono_native_thread_id_equals (MonoNativeThreadId id1, MonoNativeThreadId id2) MONO_INTERNAL;
257
258 gboolean
259 mono_native_thread_create (MonoNativeThreadId *tid, gpointer func, gpointer arg) MONO_INTERNAL;
260
261 #endif /* __MONO_THREADS_H__ */