Pass type argument to MONO_LLS_FOREACH and MONO_LLS_FOREACH_SAFE in order to avoid...
[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 #endif
113
114         /*In theory, only the posix backend needs this, but having it on mach/win32 simplifies things a lot.*/
115         MonoThreadUnwindState suspend_state;
116
117         /*async call machinery, thread MUST be suspended before accessing those fields*/
118         void (*async_target)(void*);
119         void *user_data;
120 } MonoThreadInfo;
121
122 typedef struct {
123         void* (*thread_register)(THREAD_INFO_TYPE *info, void *baseaddr);
124         /*
125         This callback is called after @info is removed from the thread list.
126         SMR remains functional as its small_id has not been reclaimed.
127         */
128         void (*thread_unregister)(THREAD_INFO_TYPE *info);
129         void (*thread_attach)(THREAD_INFO_TYPE *info);
130         gboolean (*mono_method_is_critical) (void *method);
131 #ifndef HOST_WIN32
132         int (*mono_gc_pthread_create) (pthread_t *new_thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);
133 #endif
134 } MonoThreadInfoCallbacks;
135
136 typedef struct {
137         void (*setup_async_callback) (MonoContext *ctx, void (*async_cb)(void *fun), gpointer user_data);
138         gboolean (*thread_state_init_from_sigctx) (MonoThreadUnwindState *state, void *sigctx);
139         gboolean (*thread_state_init_from_handle) (MonoThreadUnwindState *tctx, MonoNativeThreadId thread_id, MonoNativeThreadHandle thread_handle);
140 } MonoThreadInfoRuntimeCallbacks;
141
142 /*
143 Requires the world to be stoped
144 */
145 #define FOREACH_THREAD(thread) MONO_LLS_FOREACH (mono_thread_info_list_head (), thread, SgenThreadInfo*)
146 #define END_FOREACH_THREAD MONO_LLS_END_FOREACH
147
148 /*
149 Snapshot iteration.
150 */
151 #define FOREACH_THREAD_SAFE(thread) MONO_LLS_FOREACH_SAFE (mono_thread_info_list_head (), thread, SgenThreadInfo*)
152 #define END_FOREACH_THREAD_SAFE MONO_LLS_END_FOREACH_SAFE
153
154 #define mono_thread_info_get_tid(info) ((MonoNativeThreadId)((MonoThreadInfo*)info)->node.key)
155 #define mono_thread_info_set_tid(info, val) do { ((MonoThreadInfo*)(info))->node.key = (uintptr_t)(val); } while (0)
156
157 /*
158  * @thread_info_size is sizeof (GcThreadInfo), a struct the GC defines to make it possible to have
159  * a single block with info from both camps. 
160  */
161 void
162 mono_threads_init (MonoThreadInfoCallbacks *callbacks, size_t thread_info_size) MONO_INTERNAL;
163
164 void
165 mono_threads_runtime_init (MonoThreadInfoRuntimeCallbacks *callbacks) MONO_INTERNAL;
166
167 MonoThreadInfoCallbacks *
168 mono_threads_get_callbacks (void) MONO_INTERNAL;
169
170 MonoThreadInfoRuntimeCallbacks *
171 mono_threads_get_runtime_callbacks (void) MONO_INTERNAL;
172
173 int
174 mono_thread_info_register_small_id (void) MONO_INTERNAL;
175
176 THREAD_INFO_TYPE *
177 mono_thread_info_attach (void *baseptr) MONO_INTERNAL;
178
179 void
180 mono_thread_info_dettach (void) MONO_INTERNAL;
181
182 THREAD_INFO_TYPE *
183 mono_thread_info_current (void) MONO_INTERNAL;
184
185 int
186 mono_thread_info_get_small_id (void) MONO_INTERNAL;
187
188 MonoLinkedListSet*
189 mono_thread_info_list_head (void) MONO_INTERNAL;
190
191 MonoThreadInfo*
192 mono_thread_info_lookup (MonoNativeThreadId id) MONO_INTERNAL;
193
194 MonoThreadInfo*
195 mono_thread_info_safe_suspend_sync (MonoNativeThreadId tid, gboolean interrupt_kernel) MONO_INTERNAL;
196
197 gboolean
198 mono_thread_info_resume (MonoNativeThreadId tid) MONO_INTERNAL;
199
200 void
201 mono_thread_info_self_suspend (void) MONO_INTERNAL;
202
203 gboolean
204 mono_thread_info_new_interrupt_enabled (void) MONO_INTERNAL;
205
206 void
207 mono_thread_info_setup_async_call (MonoThreadInfo *info, void (*target_func)(void*), void *user_data) MONO_INTERNAL;
208
209 void
210 mono_thread_info_suspend_lock (void) MONO_INTERNAL;
211
212 void
213 mono_thread_info_suspend_unlock (void) MONO_INTERNAL;
214
215 void
216 mono_threads_unregister_current_thread (THREAD_INFO_TYPE *info) MONO_INTERNAL;
217
218 void
219 mono_thread_info_disable_new_interrupt (gboolean disable) MONO_INTERNAL;
220
221 void
222 mono_thread_info_abort_socket_syscall_for_close (MonoNativeThreadId tid) MONO_INTERNAL;
223
224 #if !defined(HOST_WIN32)
225
226 int
227 mono_threads_pthread_create (pthread_t *new_thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg) MONO_INTERNAL;
228
229 #if !defined(__MACH__)
230 /*Use this instead of pthread_kill */
231 int
232 mono_threads_pthread_kill (THREAD_INFO_TYPE *info, int signum) MONO_INTERNAL;
233 #endif
234
235 #else  /* !defined(HOST_WIN32) */
236
237 HANDLE
238         mono_threads_CreateThread (LPSECURITY_ATTRIBUTES attributes, SIZE_T stack_size, LPTHREAD_START_ROUTINE start_routine, LPVOID arg, DWORD creation_flags, LPDWORD thread_id);
239
240
241 #endif /* !defined(HOST_WIN32) */
242
243 /* Plartform specific functions DON'T use them */
244 void mono_threads_init_platform (void) MONO_INTERNAL; //ok
245 gboolean mono_threads_core_suspend (MonoThreadInfo *info) MONO_INTERNAL;
246 gboolean mono_threads_core_resume (MonoThreadInfo *info) MONO_INTERNAL;
247 void mono_threads_platform_register (MonoThreadInfo *info) MONO_INTERNAL; //ok
248 void mono_threads_platform_free (MonoThreadInfo *info) MONO_INTERNAL;
249 void mono_threads_core_interrupt (MonoThreadInfo *info) MONO_INTERNAL;
250 void mono_threads_core_abort_syscall (MonoThreadInfo *info) MONO_INTERNAL;
251 gboolean mono_threads_core_needs_abort_syscall (void) MONO_INTERNAL;
252
253 MonoNativeThreadId mono_native_thread_id_get (void) MONO_INTERNAL;
254
255 gboolean mono_native_thread_id_equals (MonoNativeThreadId id1, MonoNativeThreadId id2) MONO_INTERNAL;
256
257 gboolean
258 mono_native_thread_create (MonoNativeThreadId *tid, gpointer func, gpointer arg) MONO_INTERNAL;
259
260 #endif /* __MONO_THREADS_H__ */