Fill out AssemblyName.ProcessorArchitecture for assemblies. Fixes #15347.
[mono.git] / mono / metadata / threads.c
1 /*
2  * threads.c: Thread support internal calls
3  *
4  * Author:
5  *      Dick Porter (dick@ximian.com)
6  *      Paolo Molaro (lupus@ximian.com)
7  *      Patrik Torstensson (patrik.torstensson@labs2.com)
8  *
9  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
10  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
11  * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
12  */
13
14 #include <config.h>
15
16 #include <glib.h>
17 #include <signal.h>
18 #include <string.h>
19
20 #if defined(__OpenBSD__) || defined(__FreeBSD__)
21 #include <pthread.h>
22 #include <pthread_np.h>
23 #endif
24
25 #include <mono/metadata/object.h>
26 #include <mono/metadata/domain-internals.h>
27 #include <mono/metadata/profiler-private.h>
28 #include <mono/metadata/threads.h>
29 #include <mono/metadata/threadpool.h>
30 #include <mono/metadata/threads-types.h>
31 #include <mono/metadata/exception.h>
32 #include <mono/metadata/environment.h>
33 #include <mono/metadata/monitor.h>
34 #include <mono/metadata/gc-internal.h>
35 #include <mono/metadata/marshal.h>
36 #include <mono/metadata/runtime.h>
37 #include <mono/io-layer/io-layer.h>
38 #ifndef HOST_WIN32
39 #include <mono/io-layer/threads.h>
40 #endif
41 #include <mono/metadata/object-internals.h>
42 #include <mono/metadata/mono-debug-debugger.h>
43 #include <mono/utils/mono-compiler.h>
44 #include <mono/utils/mono-mmap.h>
45 #include <mono/utils/mono-membar.h>
46 #include <mono/utils/mono-time.h>
47 #include <mono/utils/mono-threads.h>
48 #include <mono/utils/hazard-pointer.h>
49 #include <mono/utils/mono-tls.h>
50 #include <mono/utils/atomic.h>
51
52 #include <mono/metadata/gc-internal.h>
53
54 #ifdef PLATFORM_ANDROID
55 #include <errno.h>
56
57 extern int tkill (pid_t tid, int signal);
58 #endif
59
60 #if defined(PLATFORM_MACOSX) && defined(HAVE_PTHREAD_GET_STACKADDR_NP)
61 void *pthread_get_stackaddr_np(pthread_t);
62 size_t pthread_get_stacksize_np(pthread_t);
63 #endif
64
65 /*#define THREAD_DEBUG(a) do { a; } while (0)*/
66 #define THREAD_DEBUG(a)
67 /*#define THREAD_WAIT_DEBUG(a) do { a; } while (0)*/
68 #define THREAD_WAIT_DEBUG(a)
69 /*#define LIBGC_DEBUG(a) do { a; } while (0)*/
70 #define LIBGC_DEBUG(a)
71
72 #define SPIN_TRYLOCK(i) (InterlockedCompareExchange (&(i), 1, 0) == 0)
73 #define SPIN_LOCK(i) do { \
74                                 if (SPIN_TRYLOCK (i)) \
75                                         break; \
76                         } while (1)
77
78 #define SPIN_UNLOCK(i) i = 0
79
80 /* Provide this for systems with glib < 2.6 */
81 #ifndef G_GSIZE_FORMAT
82 #   if GLIB_SIZEOF_LONG == 8
83 #       define G_GSIZE_FORMAT "lu"
84 #   else
85 #       define G_GSIZE_FORMAT "u"
86 #   endif
87 #endif
88
89 struct StartInfo 
90 {
91         guint32 (*func)(void *);
92         MonoThread *obj;
93         MonoObject *delegate;
94         void *start_arg;
95 };
96
97 typedef union {
98         gint32 ival;
99         gfloat fval;
100 } IntFloatUnion;
101
102 typedef union {
103         gint64 ival;
104         gdouble fval;
105 } LongDoubleUnion;
106  
107 typedef struct _MonoThreadDomainTls MonoThreadDomainTls;
108 struct _MonoThreadDomainTls {
109         MonoThreadDomainTls *next;
110         guint32 offset;
111         guint32 size;
112 };
113
114 typedef struct {
115         int idx;
116         int offset;
117         MonoThreadDomainTls *freelist;
118 } StaticDataInfo;
119
120 /* Number of cached culture objects in the MonoThread->cached_culture_info array
121  * (per-type): we use the first NUM entries for CultureInfo and the last for
122  * UICultureInfo. So the size of the array is really NUM_CACHED_CULTURES * 2.
123  */
124 #define NUM_CACHED_CULTURES 4
125 #define CULTURES_START_IDX 0
126 #define UICULTURES_START_IDX NUM_CACHED_CULTURES
127
128 /* Controls access to the 'threads' hash table */
129 #define mono_threads_lock() EnterCriticalSection (&threads_mutex)
130 #define mono_threads_unlock() LeaveCriticalSection (&threads_mutex)
131 static CRITICAL_SECTION threads_mutex;
132
133 /* Controls access to context static data */
134 #define mono_contexts_lock() EnterCriticalSection (&contexts_mutex)
135 #define mono_contexts_unlock() LeaveCriticalSection (&contexts_mutex)
136 static CRITICAL_SECTION contexts_mutex;
137
138 /* Holds current status of static data heap */
139 static StaticDataInfo thread_static_info;
140 static StaticDataInfo context_static_info;
141
142 /* The hash of existing threads (key is thread ID, value is
143  * MonoInternalThread*) that need joining before exit
144  */
145 static MonoGHashTable *threads=NULL;
146
147 /*
148  * Threads which are starting up and they are not in the 'threads' hash yet.
149  * When handle_store is called for a thread, it will be removed from this hash table.
150  * Protected by mono_threads_lock ().
151  */
152 static MonoGHashTable *threads_starting_up = NULL;
153  
154 /* Maps a MonoThread to its start argument */
155 /* Protected by mono_threads_lock () */
156 static MonoGHashTable *thread_start_args = NULL;
157
158 /* The TLS key that holds the MonoObject assigned to each thread */
159 static MonoNativeTlsKey current_object_key;
160
161 #ifdef MONO_HAVE_FAST_TLS
162 /* we need to use both the Tls* functions and __thread because
163  * the gc needs to see all the threads 
164  */
165 MONO_FAST_TLS_DECLARE(tls_current_object);
166 #define SET_CURRENT_OBJECT(x) do { \
167         MONO_FAST_TLS_SET (tls_current_object, x); \
168         mono_native_tls_set_value (current_object_key, x); \
169 } while (FALSE)
170 #define GET_CURRENT_OBJECT() ((MonoInternalThread*) MONO_FAST_TLS_GET (tls_current_object))
171 #else
172 #define SET_CURRENT_OBJECT(x) mono_native_tls_set_value (current_object_key, x)
173 #define GET_CURRENT_OBJECT() (MonoInternalThread*) mono_native_tls_get_value (current_object_key)
174 #endif
175
176 /* function called at thread start */
177 static MonoThreadStartCB mono_thread_start_cb = NULL;
178
179 /* function called at thread attach */
180 static MonoThreadAttachCB mono_thread_attach_cb = NULL;
181
182 /* function called at thread cleanup */
183 static MonoThreadCleanupFunc mono_thread_cleanup_fn = NULL;
184
185 /* function called to notify the runtime about a pending exception on the current thread */
186 static MonoThreadNotifyPendingExcFunc mono_thread_notify_pending_exc_fn = NULL;
187
188 /* The default stack size for each thread */
189 static guint32 default_stacksize = 0;
190 #define default_stacksize_for_thread(thread) ((thread)->stack_size? (thread)->stack_size: default_stacksize)
191
192 static void thread_adjust_static_data (MonoInternalThread *thread);
193 static void mono_free_static_data (gpointer* static_data, gboolean threadlocal);
194 static void mono_init_static_data_info (StaticDataInfo *static_data);
195 static guint32 mono_alloc_static_data_slot (StaticDataInfo *static_data, guint32 size, guint32 align);
196 static gboolean mono_thread_resume (MonoInternalThread* thread);
197 static void mono_thread_start (MonoThread *thread);
198 static void signal_thread_state_change (MonoInternalThread *thread);
199 static void abort_thread_internal (MonoInternalThread *thread, gboolean can_raise_exception, gboolean install_async_abort);
200 static void suspend_thread_internal (MonoInternalThread *thread, gboolean interrupt);
201 static void self_suspend_internal (MonoInternalThread *thread);
202 static gboolean resume_thread_internal (MonoInternalThread *thread);
203
204 static MonoException* mono_thread_execute_interruption (MonoInternalThread *thread);
205 static void ref_stack_destroy (gpointer rs);
206
207 /* Spin lock for InterlockedXXX 64 bit functions */
208 #define mono_interlocked_lock() EnterCriticalSection (&interlocked_mutex)
209 #define mono_interlocked_unlock() LeaveCriticalSection (&interlocked_mutex)
210 static CRITICAL_SECTION interlocked_mutex;
211
212 /* global count of thread interruptions requested */
213 static gint32 thread_interruption_requested = 0;
214
215 /* Event signaled when a thread changes its background mode */
216 static HANDLE background_change_event;
217
218 static gboolean shutting_down = FALSE;
219
220 static gint32 managed_thread_id_counter = 0;
221
222 static guint32
223 get_next_managed_thread_id (void)
224 {
225         return InterlockedIncrement (&managed_thread_id_counter);
226 }
227
228 MonoNativeTlsKey
229 mono_thread_get_tls_key (void)
230 {
231         return current_object_key;
232 }
233
234 gint32
235 mono_thread_get_tls_offset (void)
236 {
237         int offset;
238         MONO_THREAD_VAR_OFFSET (tls_current_object,offset);
239         return offset;
240 }
241
242 /* handle_store() and handle_remove() manage the array of threads that
243  * still need to be waited for when the main thread exits.
244  *
245  * If handle_store() returns FALSE the thread must not be started
246  * because Mono is shutting down.
247  */
248 static gboolean handle_store(MonoThread *thread, gboolean force_attach)
249 {
250         mono_threads_lock ();
251
252         THREAD_DEBUG (g_message ("%s: thread %p ID %"G_GSIZE_FORMAT, __func__, thread, (gsize)thread->internal_thread->tid));
253
254         if (threads_starting_up)
255                 mono_g_hash_table_remove (threads_starting_up, thread);
256
257         if (shutting_down && !force_attach) {
258                 mono_threads_unlock ();
259                 return FALSE;
260         }
261
262         if(threads==NULL) {
263                 MONO_GC_REGISTER_ROOT_FIXED (threads);
264                 threads=mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
265         }
266
267         /* We don't need to duplicate thread->handle, because it is
268          * only closed when the thread object is finalized by the GC.
269          */
270         g_assert (thread->internal_thread);
271         mono_g_hash_table_insert(threads, (gpointer)(gsize)(thread->internal_thread->tid),
272                                  thread->internal_thread);
273
274         mono_threads_unlock ();
275
276         return TRUE;
277 }
278
279 static gboolean handle_remove(MonoInternalThread *thread)
280 {
281         gboolean ret;
282         gsize tid = thread->tid;
283
284         THREAD_DEBUG (g_message ("%s: thread ID %"G_GSIZE_FORMAT, __func__, tid));
285
286         mono_threads_lock ();
287
288         if (threads) {
289                 /* We have to check whether the thread object for the
290                  * tid is still the same in the table because the
291                  * thread might have been destroyed and the tid reused
292                  * in the meantime, in which case the tid would be in
293                  * the table, but with another thread object.
294                  */
295                 if (mono_g_hash_table_lookup (threads, (gpointer)tid) == thread) {
296                         mono_g_hash_table_remove (threads, (gpointer)tid);
297                         ret = TRUE;
298                 } else {
299                         ret = FALSE;
300                 }
301         }
302         else
303                 ret = FALSE;
304         
305         mono_threads_unlock ();
306
307         /* Don't close the handle here, wait for the object finalizer
308          * to do it. Otherwise, the following race condition applies:
309          *
310          * 1) Thread exits (and handle_remove() closes the handle)
311          *
312          * 2) Some other handle is reassigned the same slot
313          *
314          * 3) Another thread tries to join the first thread, and
315          * blocks waiting for the reassigned handle to be signalled
316          * (which might never happen).  This is possible, because the
317          * thread calling Join() still has a reference to the first
318          * thread's object.
319          */
320         return ret;
321 }
322
323 static void ensure_synch_cs_set (MonoInternalThread *thread)
324 {
325         CRITICAL_SECTION *synch_cs;
326         
327         if (thread->synch_cs != NULL) {
328                 return;
329         }
330         
331         synch_cs = g_new0 (CRITICAL_SECTION, 1);
332         InitializeCriticalSection (synch_cs);
333         
334         if (InterlockedCompareExchangePointer ((gpointer *)&thread->synch_cs,
335                                                synch_cs, NULL) != NULL) {
336                 /* Another thread must have installed this CS */
337                 DeleteCriticalSection (synch_cs);
338                 g_free (synch_cs);
339         }
340 }
341
342 /*
343  * NOTE: this function can be called also for threads different from the current one:
344  * make sure no code called from it will ever assume it is run on the thread that is
345  * getting cleaned up.
346  */
347 static void thread_cleanup (MonoInternalThread *thread)
348 {
349         g_assert (thread != NULL);
350
351         if (thread->abort_state_handle) {
352                 mono_gchandle_free (thread->abort_state_handle);
353                 thread->abort_state_handle = 0;
354         }
355         thread->abort_exc = NULL;
356         thread->current_appcontext = NULL;
357
358         /*
359          * This is necessary because otherwise we might have
360          * cross-domain references which will not get cleaned up when
361          * the target domain is unloaded.
362          */
363         if (thread->cached_culture_info) {
364                 int i;
365                 for (i = 0; i < NUM_CACHED_CULTURES * 2; ++i)
366                         mono_array_set (thread->cached_culture_info, MonoObject*, i, NULL);
367         }
368
369         ensure_synch_cs_set (thread);
370
371         EnterCriticalSection (thread->synch_cs);
372
373         thread->state |= ThreadState_Stopped;
374         thread->state &= ~ThreadState_Background;
375
376         LeaveCriticalSection (thread->synch_cs);
377
378         /*
379         An interruption request has leaked to cleanup. Adjust the global counter.
380
381         This can happen is the abort source thread finds the abortee (this) thread
382         in unmanaged code. If this thread never trips back to managed code or check
383         the local flag it will be left set and positively unbalance the global counter.
384         
385         Leaving the counter unbalanced will cause a performance degradation since all threads
386         will now keep checking their local flags all the time.
387         */
388         if (InterlockedExchange (&thread->interruption_requested, 0))
389                 InterlockedDecrement (&thread_interruption_requested);
390
391         /* if the thread is not in the hash it has been removed already */
392         if (!handle_remove (thread)) {
393                 if (thread == mono_thread_internal_current ()) {
394                         mono_domain_unset ();
395                         mono_memory_barrier ();
396                 }
397                 /* This needs to be called even if handle_remove () fails */
398                 if (mono_thread_cleanup_fn)
399                         mono_thread_cleanup_fn (thread);
400                 return;
401         }
402         mono_release_type_locks (thread);
403
404         mono_profiler_thread_end (thread->tid);
405
406         if (thread == mono_thread_internal_current ()) {
407                 /*
408                  * This will signal async signal handlers that the thread has exited.
409                  * The profiler callback needs this to be set, so it cannot be done earlier.
410                  */
411                 mono_domain_unset ();
412                 mono_memory_barrier ();
413         }
414
415         if (thread == mono_thread_internal_current ())
416                 mono_thread_pop_appdomain_ref ();
417
418         thread->cached_culture_info = NULL;
419
420         mono_free_static_data (thread->static_data, TRUE);
421         thread->static_data = NULL;
422         ref_stack_destroy (thread->appdomain_refs);
423         thread->appdomain_refs = NULL;
424
425         if (mono_thread_cleanup_fn)
426                 mono_thread_cleanup_fn (thread);
427
428         if (mono_gc_is_moving ()) {
429                 MONO_GC_UNREGISTER_ROOT (thread->thread_pinning_ref);
430                 thread->thread_pinning_ref = NULL;
431         }
432                 
433 }
434
435 static gpointer
436 get_thread_static_data (MonoInternalThread *thread, guint32 offset)
437 {
438         int idx;
439         g_assert ((offset & 0x80000000) == 0);
440         offset &= 0x7fffffff;
441         idx = (offset >> 24) - 1;
442         return ((char*) thread->static_data [idx]) + (offset & 0xffffff);
443 }
444
445 static MonoThread**
446 get_current_thread_ptr_for_domain (MonoDomain *domain, MonoInternalThread *thread)
447 {
448         static MonoClassField *current_thread_field = NULL;
449
450         guint32 offset;
451
452         if (!current_thread_field) {
453                 current_thread_field = mono_class_get_field_from_name (mono_defaults.thread_class, "current_thread");
454                 g_assert (current_thread_field);
455         }
456
457         mono_class_vtable (domain, mono_defaults.thread_class);
458         mono_domain_lock (domain);
459         offset = GPOINTER_TO_UINT (g_hash_table_lookup (domain->special_static_fields, current_thread_field));
460         mono_domain_unlock (domain);
461         g_assert (offset);
462
463         return get_thread_static_data (thread, offset);
464 }
465
466 static void
467 set_current_thread_for_domain (MonoDomain *domain, MonoInternalThread *thread, MonoThread *current)
468 {
469         MonoThread **current_thread_ptr = get_current_thread_ptr_for_domain (domain, thread);
470
471         g_assert (current->obj.vtable->domain == domain);
472
473         g_assert (!*current_thread_ptr);
474         *current_thread_ptr = current;
475 }
476
477 static MonoInternalThread*
478 create_internal_thread_object (void)
479 {
480         MonoVTable *vt = mono_class_vtable (mono_get_root_domain (), mono_defaults.internal_thread_class);
481         return (MonoInternalThread*)mono_gc_alloc_mature (vt);
482 }
483
484 static MonoThread*
485 create_thread_object (MonoDomain *domain)
486 {
487         MonoVTable *vt = mono_class_vtable (domain, mono_defaults.thread_class);
488         return (MonoThread*)mono_gc_alloc_mature (vt);
489 }
490
491 static MonoThread*
492 new_thread_with_internal (MonoDomain *domain, MonoInternalThread *internal)
493 {
494         MonoThread *thread = create_thread_object (domain);
495         MONO_OBJECT_SETREF (thread, internal_thread, internal);
496         return thread;
497 }
498
499 static void
500 init_root_domain_thread (MonoInternalThread *thread, MonoThread *candidate)
501 {
502         MonoDomain *domain = mono_get_root_domain ();
503
504         if (!candidate || candidate->obj.vtable->domain != domain)
505                 candidate = new_thread_with_internal (domain, thread);
506         set_current_thread_for_domain (domain, thread, candidate);
507         g_assert (!thread->root_domain_thread);
508         MONO_OBJECT_SETREF (thread, root_domain_thread, candidate);
509 }
510
511 static guint32 WINAPI start_wrapper_internal(void *data)
512 {
513         MonoThreadInfo *info;
514         struct StartInfo *start_info=(struct StartInfo *)data;
515         guint32 (*start_func)(void *);
516         void *start_arg;
517         gsize tid;
518         /* 
519          * We don't create a local to hold start_info->obj, so hopefully it won't get pinned during a
520          * GC stack walk.
521          */
522         MonoInternalThread *internal = start_info->obj->internal_thread;
523         MonoObject *start_delegate = start_info->delegate;
524         MonoDomain *domain = start_info->obj->obj.vtable->domain;
525
526         THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Start wrapper", __func__, GetCurrentThreadId ()));
527
528         /* We can be sure start_info->obj->tid and
529          * start_info->obj->handle have been set, because the thread
530          * was created suspended, and these values were set before the
531          * thread resumed
532          */
533
534         info = mono_thread_info_current ();
535         g_assert (info);
536         internal->thread_info = info;
537
538
539         tid=internal->tid;
540
541         SET_CURRENT_OBJECT (internal);
542
543         mono_monitor_init_tls ();
544
545         /* Every thread references the appdomain which created it */
546         mono_thread_push_appdomain_ref (domain);
547         
548         if (!mono_domain_set (domain, FALSE)) {
549                 /* No point in raising an appdomain_unloaded exception here */
550                 /* FIXME: Cleanup here */
551                 mono_thread_pop_appdomain_ref ();
552                 return 0;
553         }
554
555         start_func = start_info->func;
556         start_arg = start_info->start_arg;
557
558         /* We have to do this here because mono_thread_new_init()
559            requires that root_domain_thread is set up. */
560         thread_adjust_static_data (internal);
561         init_root_domain_thread (internal, start_info->obj);
562
563         /* This MUST be called before any managed code can be
564          * executed, as it calls the callback function that (for the
565          * jit) sets the lmf marker.
566          */
567         mono_thread_new_init (tid, &tid, start_func);
568         internal->stack_ptr = &tid;
569
570         LIBGC_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT",%d) Setting thread stack to %p", __func__, GetCurrentThreadId (), getpid (), thread->stack_ptr));
571
572         THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Setting current_object_key to %p", __func__, GetCurrentThreadId (), internal));
573
574         /* On 2.0 profile (and higher), set explicitly since state might have been
575            Unknown */
576         if (internal->apartment_state == ThreadApartmentState_Unknown)
577                 internal->apartment_state = ThreadApartmentState_MTA;
578
579         mono_thread_init_apartment_state ();
580
581         if(internal->start_notify!=NULL) {
582                 /* Let the thread that called Start() know we're
583                  * ready
584                  */
585                 ReleaseSemaphore (internal->start_notify, 1, NULL);
586         }
587
588         mono_threads_lock ();
589         mono_g_hash_table_remove (thread_start_args, start_info->obj);
590         mono_threads_unlock ();
591
592         mono_thread_set_execution_context (start_info->obj->ec_to_set);
593         start_info->obj->ec_to_set = NULL;
594
595         g_free (start_info);
596         THREAD_DEBUG (g_message ("%s: start_wrapper for %"G_GSIZE_FORMAT, __func__,
597                                                          internal->tid));
598
599         /* 
600          * Call this after calling start_notify, since the profiler callback might want
601          * to lock the thread, and the lock is held by thread_start () which waits for
602          * start_notify.
603          */
604         mono_profiler_thread_start (tid);
605
606         /* start_func is set only for unmanaged start functions */
607         if (start_func) {
608                 start_func (start_arg);
609         } else {
610                 void *args [1];
611                 g_assert (start_delegate != NULL);
612                 args [0] = start_arg;
613                 /* we may want to handle the exception here. See comment below on unhandled exceptions */
614                 mono_runtime_delegate_invoke (start_delegate, args, NULL);
615         }
616
617         /* If the thread calls ExitThread at all, this remaining code
618          * will not be executed, but the main thread will eventually
619          * call thread_cleanup() on this thread's behalf.
620          */
621
622         THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Start wrapper terminating", __func__, GetCurrentThreadId ()));
623
624         /* Do any cleanup needed for apartment state. This
625          * cannot be done in thread_cleanup since thread_cleanup could be 
626          * called for a thread other than the current thread.
627          * mono_thread_cleanup_apartment_state cleans up apartment
628          * for the current thead */
629         mono_thread_cleanup_apartment_state ();
630
631         thread_cleanup (internal);
632
633         /* Remove the reference to the thread object in the TLS data,
634          * so the thread object can be finalized.  This won't be
635          * reached if the thread threw an uncaught exception, so those
636          * thread handles will stay referenced :-( (This is due to
637          * missing support for scanning thread-specific data in the
638          * Boehm GC - the io-layer keeps a GC-visible hash of pointers
639          * to TLS data.)
640          */
641         SET_CURRENT_OBJECT (NULL);
642
643         return(0);
644 }
645
646 static guint32 WINAPI start_wrapper(void *data)
647 {
648         volatile int dummy;
649
650         /* Avoid scanning the frames above this frame during a GC */
651         mono_gc_set_stack_end ((void*)&dummy);
652
653         return start_wrapper_internal (data);
654 }
655
656 void mono_thread_new_init (intptr_t tid, gpointer stack_start, gpointer func)
657 {
658         if (mono_thread_start_cb) {
659                 mono_thread_start_cb (tid, stack_start, func);
660         }
661 }
662
663 void mono_threads_set_default_stacksize (guint32 stacksize)
664 {
665         default_stacksize = stacksize;
666 }
667
668 guint32 mono_threads_get_default_stacksize (void)
669 {
670         return default_stacksize;
671 }
672
673 /*
674  * mono_create_thread:
675  *
676  *   This is a wrapper around CreateThread which handles differences in the type of
677  * the the 'tid' argument.
678  */
679 gpointer mono_create_thread (WapiSecurityAttributes *security,
680                                                          guint32 stacksize, WapiThreadStart start,
681                                                          gpointer param, guint32 create, gsize *tid)
682 {
683         gpointer res;
684
685 #ifdef HOST_WIN32
686         DWORD real_tid;
687
688         res = mono_threads_CreateThread (security, stacksize, start, param, create, &real_tid);
689         if (tid)
690                 *tid = real_tid;
691 #else
692         res = CreateThread (security, stacksize, start, param, create, tid);
693 #endif
694
695         return res;
696 }
697
698 /* 
699  * The thread start argument may be an object reference, and there is
700  * no ref to keep it alive when the new thread is started but not yet
701  * registered with the collector. So we store it in a GC tracked hash
702  * table.
703  *
704  * LOCKING: Assumes the threads lock is held.
705  */
706 static void
707 register_thread_start_argument (MonoThread *thread, struct StartInfo *start_info)
708 {
709         if (thread_start_args == NULL) {
710                 MONO_GC_REGISTER_ROOT_FIXED (thread_start_args);
711                 thread_start_args = mono_g_hash_table_new (NULL, NULL);
712         }
713         mono_g_hash_table_insert (thread_start_args, thread, start_info->start_arg);
714 }
715
716 /*
717  * mono_thread_create_internal:
718  * 
719  * If NO_DETACH is TRUE, then the thread is not detached using pthread_detach (). This is needed to fix the race condition where waiting for a thred to exit only waits for its exit event to be
720  * signalled, which can cause shutdown crashes if the thread shutdown code accesses data already freed by the runtime shutdown.
721  * Currently, this is only used for the finalizer thread.
722  */
723 MonoInternalThread*
724 mono_thread_create_internal (MonoDomain *domain, gpointer func, gpointer arg, gboolean threadpool_thread, gboolean no_detach, guint32 stack_size)
725 {
726         MonoThread *thread;
727         MonoInternalThread *internal;
728         HANDLE thread_handle;
729         struct StartInfo *start_info;
730         gsize tid;
731         guint32 create_flags;
732
733         thread = create_thread_object (domain);
734         internal = create_internal_thread_object ();
735         MONO_OBJECT_SETREF (thread, internal_thread, internal);
736
737         start_info=g_new0 (struct StartInfo, 1);
738         start_info->func = func;
739         start_info->obj = thread;
740         start_info->start_arg = arg;
741
742         mono_threads_lock ();
743         if (shutting_down) {
744                 mono_threads_unlock ();
745                 g_free (start_info);
746                 return NULL;
747         }
748         if (threads_starting_up == NULL) {
749                 MONO_GC_REGISTER_ROOT_FIXED (threads_starting_up);
750                 threads_starting_up = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_VALUE_GC);
751         }
752
753         register_thread_start_argument (thread, start_info);
754         mono_g_hash_table_insert (threads_starting_up, thread, thread);
755         mono_threads_unlock (); 
756
757         if (stack_size == 0)
758                 stack_size = default_stacksize_for_thread (internal);
759
760         /* Create suspended, so we can do some housekeeping before the thread
761          * starts
762          */
763         create_flags = CREATE_SUSPENDED;
764 #ifndef HOST_WIN32
765         if (no_detach)
766                 create_flags |= CREATE_NO_DETACH;
767 #endif
768         thread_handle = mono_create_thread (NULL, stack_size, (LPTHREAD_START_ROUTINE)start_wrapper, start_info,
769                                      create_flags, &tid);
770         THREAD_DEBUG (g_message ("%s: Started thread ID %"G_GSIZE_FORMAT" (handle %p)", __func__, tid, thread_handle));
771         if (thread_handle == NULL) {
772                 /* The thread couldn't be created, so throw an exception */
773                 mono_threads_lock ();
774                 mono_g_hash_table_remove (threads_starting_up, thread);
775                 mono_threads_unlock ();
776                 g_free (start_info);
777                 mono_raise_exception (mono_get_exception_execution_engine ("Couldn't create thread"));
778                 return NULL;
779         }
780
781         internal->handle=thread_handle;
782         internal->tid=tid;
783         internal->apartment_state=ThreadApartmentState_Unknown;
784         internal->managed_id = get_next_managed_thread_id ();
785         if (mono_gc_is_moving ()) {
786                 internal->thread_pinning_ref = internal;
787                 MONO_GC_REGISTER_ROOT_PINNING (internal->thread_pinning_ref);
788         }
789
790         internal->synch_cs = g_new0 (CRITICAL_SECTION, 1);
791         InitializeCriticalSection (internal->synch_cs);
792
793         internal->threadpool_thread = threadpool_thread;
794         if (threadpool_thread)
795                 mono_thread_set_state (internal, ThreadState_Background);
796
797         if (handle_store (thread, FALSE))
798                 ResumeThread (thread_handle);
799
800         /* Check that the managed and unmanaged layout of MonoInternalThread matches */
801         if (mono_check_corlib_version () == NULL)
802                 g_assert (((char*)&internal->unused2 - (char*)internal) == mono_defaults.internal_thread_class->fields [mono_defaults.internal_thread_class->field.count - 1].offset);
803
804         return internal;
805 }
806
807 void
808 mono_thread_create (MonoDomain *domain, gpointer func, gpointer arg)
809 {
810         mono_thread_create_internal (domain, func, arg, FALSE, FALSE, 0);
811 }
812
813 #if defined(HOST_WIN32) && defined(__GNUC__)
814 static __inline__ __attribute__((always_inline))
815 /* This is not defined by gcc */
816 unsigned long long
817 __readfsdword (unsigned long offset)
818 {
819         unsigned long value;
820         //      __asm__("movl %%fs:%a[offset], %k[value]" : [value] "=q" (value) : [offset] "irm" (offset));
821    __asm__ volatile ("movl    %%fs:%1,%0"
822      : "=r" (value) ,"=m" ((*(volatile long *) offset)));
823         return value;
824 }
825 #endif
826
827 /*
828  * mono_thread_get_stack_bounds:
829  *
830  *   Return the address and size of the current threads stack. Return NULL as the 
831  * stack address if the stack address cannot be determined.
832  */
833 void
834 mono_thread_get_stack_bounds (guint8 **staddr, size_t *stsize)
835 {
836 #if defined(HOST_WIN32)
837         /* Windows */
838         /* http://en.wikipedia.org/wiki/Win32_Thread_Information_Block */
839         void* tib = (void*)__readfsdword(0x18);
840         guint8 *stackTop = (guint8*)*(int*)((char*)tib + 4);
841         guint8 *stackBottom = (guint8*)*(int*)((char*)tib + 8);
842
843         *staddr = stackBottom;
844         *stsize = stackTop - stackBottom;
845         return;
846
847 #elif defined(HAVE_PTHREAD_GET_STACKSIZE_NP) && defined(HAVE_PTHREAD_GET_STACKADDR_NP)
848         /* Mac OS X */
849         *staddr = (guint8*)pthread_get_stackaddr_np (pthread_self());
850         *stsize = pthread_get_stacksize_np (pthread_self());
851
852         /* staddr points to the start of the stack, not the end */
853         *staddr -= *stsize;
854
855         /* When running under emacs, sometimes staddr is not aligned to a page size */
856         *staddr = (guint8*)((gssize)*staddr & ~(mono_pagesize() - 1));
857         return;
858
859 #elif (defined(HAVE_PTHREAD_GETATTR_NP) || defined(HAVE_PTHREAD_ATTR_GET_NP)) && defined(HAVE_PTHREAD_ATTR_GETSTACK)
860         /* Linux, BSD */
861
862         pthread_attr_t attr;
863         guint8 *current = (guint8*)&attr;
864
865         *staddr = NULL;
866         *stsize = (size_t)-1;
867
868         pthread_attr_init (&attr);
869
870 #if     defined(HAVE_PTHREAD_GETATTR_NP)
871         /* Linux */
872         pthread_getattr_np (pthread_self(), &attr);
873
874 #elif   defined(HAVE_PTHREAD_ATTR_GET_NP)
875         /* BSD */
876         pthread_attr_get_np (pthread_self(), &attr);
877
878 #else
879 #error  Cannot determine which API is needed to retrieve pthread attributes.
880 #endif
881
882         pthread_attr_getstack (&attr, (void**)staddr, stsize);
883         pthread_attr_destroy (&attr);
884
885         if (*staddr)
886                 g_assert ((current > *staddr) && (current < *staddr + *stsize));
887
888         /* When running under emacs, sometimes staddr is not aligned to a page size */
889         *staddr = (guint8*)((gssize)*staddr & ~(mono_pagesize () - 1));
890         return;
891
892 #elif defined(__OpenBSD__)
893         /* OpenBSD */
894         /* TODO :   Determine if this code is actually still needed. It may already be covered by the case above. */
895
896         pthread_attr_t attr;
897         guint8 *current = (guint8*)&attr;
898
899         *staddr = NULL;
900         *stsize = (size_t)-1;
901
902         pthread_attr_init (&attr);
903
904         stack_t ss;
905         int rslt;
906
907         rslt = pthread_stackseg_np(pthread_self(), &ss);
908         g_assert (rslt == 0);
909
910         *staddr = (guint8*)((size_t)ss.ss_sp - ss.ss_size);
911         *stsize = ss.ss_size;
912
913         pthread_attr_destroy (&attr);
914
915         if (*staddr)
916                 g_assert ((current > *staddr) && (current < *staddr + *stsize));
917
918         /* When running under emacs, sometimes staddr is not aligned to a page size */
919         *staddr = (guint8*)((gssize)*staddr & ~(mono_pagesize () - 1));
920         return;
921
922 #elif defined(sun) || defined(__native_client__)
923         /* Solaris/Illumos, NaCl */
924         pthread_attr_t attr;
925         pthread_attr_init (&attr);
926         pthread_attr_getstacksize (&attr, &stsize);
927         pthread_attr_destroy (&attr);
928         *staddr = NULL;
929         return;
930
931 #else
932         /* FIXME:   It'd be better to use the 'error' preprocessor macro here so we know
933                     at compile-time if the target platform isn't supported. */
934 #warning "Unable to determine how to retrieve a thread's stack-bounds for this platform in 'mono_thread_get_stack_bounds()'."
935         *staddr = NULL;
936         *stsize = 0;
937         return;
938 #endif
939 }
940
941 MonoThread *
942 mono_thread_attach (MonoDomain *domain)
943 {
944         return mono_thread_attach_full (domain, FALSE);
945 }
946
947 MonoThread *
948 mono_thread_attach_full (MonoDomain *domain, gboolean force_attach)
949 {
950         MonoThreadInfo *info;
951         MonoInternalThread *thread;
952         MonoThread *current_thread;
953         HANDLE thread_handle;
954         gsize tid;
955
956         if ((thread = mono_thread_internal_current ())) {
957                 if (domain != mono_domain_get ())
958                         mono_domain_set (domain, TRUE);
959                 /* Already attached */
960                 return mono_thread_current ();
961         }
962
963         if (!mono_gc_register_thread (&domain)) {
964                 g_error ("Thread %"G_GSIZE_FORMAT" calling into managed code is not registered with the GC. On UNIX, this can be fixed by #include-ing <gc.h> before <pthread.h> in the file containing the thread creation code.", GetCurrentThreadId ());
965         }
966
967         thread = create_internal_thread_object ();
968
969         thread_handle = GetCurrentThread ();
970         g_assert (thread_handle);
971
972         tid=GetCurrentThreadId ();
973
974         /* 
975          * The handle returned by GetCurrentThread () is a pseudo handle, so it can't be used to
976          * refer to the thread from other threads for things like aborting.
977          */
978         DuplicateHandle (GetCurrentProcess (), thread_handle, GetCurrentProcess (), &thread_handle, 
979                                          THREAD_ALL_ACCESS, TRUE, 0);
980
981         thread->handle=thread_handle;
982         thread->tid=tid;
983 #ifdef PLATFORM_ANDROID
984         thread->android_tid = (gpointer) gettid ();
985 #endif
986         thread->apartment_state=ThreadApartmentState_Unknown;
987         thread->managed_id = get_next_managed_thread_id ();
988         if (mono_gc_is_moving ()) {
989                 thread->thread_pinning_ref = thread;
990                 MONO_GC_REGISTER_ROOT_PINNING (thread->thread_pinning_ref);
991         }
992
993         thread->stack_ptr = &tid;
994
995         thread->synch_cs = g_new0 (CRITICAL_SECTION, 1);
996         InitializeCriticalSection (thread->synch_cs);
997
998         THREAD_DEBUG (g_message ("%s: Attached thread ID %"G_GSIZE_FORMAT" (handle %p)", __func__, tid, thread_handle));
999
1000         info = mono_thread_info_current ();
1001         g_assert (info);
1002         thread->thread_info = info;
1003
1004         current_thread = new_thread_with_internal (domain, thread);
1005
1006         if (!handle_store (current_thread, force_attach)) {
1007                 /* Mono is shutting down, so just wait for the end */
1008                 for (;;)
1009                         Sleep (10000);
1010         }
1011
1012         THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Setting current_object_key to %p", __func__, GetCurrentThreadId (), thread));
1013
1014         SET_CURRENT_OBJECT (thread);
1015         mono_domain_set (domain, TRUE);
1016
1017         mono_monitor_init_tls ();
1018
1019         thread_adjust_static_data (thread);
1020
1021         init_root_domain_thread (thread, current_thread);
1022         if (domain != mono_get_root_domain ())
1023                 set_current_thread_for_domain (domain, thread, current_thread);
1024
1025
1026         if (mono_thread_attach_cb) {
1027                 guint8 *staddr;
1028                 size_t stsize;
1029
1030                 mono_thread_get_stack_bounds (&staddr, &stsize);
1031
1032                 if (staddr == NULL)
1033                         mono_thread_attach_cb (tid, &tid);
1034                 else
1035                         mono_thread_attach_cb (tid, staddr + stsize);
1036         }
1037
1038         // FIXME: Need a separate callback
1039         mono_profiler_thread_start (tid);
1040
1041         return current_thread;
1042 }
1043
1044 void
1045 mono_thread_detach (MonoThread *thread)
1046 {
1047         g_return_if_fail (thread != NULL);
1048
1049         THREAD_DEBUG (g_message ("%s: mono_thread_detach for %p (%"G_GSIZE_FORMAT")", __func__, thread, (gsize)thread->internal_thread->tid));
1050
1051         thread_cleanup (thread->internal_thread);
1052
1053         SET_CURRENT_OBJECT (NULL);
1054         mono_domain_unset ();
1055
1056         /* Don't need to CloseHandle this thread, even though we took a
1057          * reference in mono_thread_attach (), because the GC will do it
1058          * when the Thread object is finalised.
1059          */
1060 }
1061
1062 void
1063 mono_thread_exit ()
1064 {
1065         MonoInternalThread *thread = mono_thread_internal_current ();
1066
1067         THREAD_DEBUG (g_message ("%s: mono_thread_exit for %p (%"G_GSIZE_FORMAT")", __func__, thread, (gsize)thread->tid));
1068
1069         thread_cleanup (thread);
1070         SET_CURRENT_OBJECT (NULL);
1071         mono_domain_unset ();
1072
1073         /* we could add a callback here for embedders to use. */
1074         if (mono_thread_get_main () && (thread == mono_thread_get_main ()->internal_thread))
1075                 exit (mono_environment_exitcode_get ());
1076         ExitThread (-1);
1077 }
1078
1079 void
1080 ves_icall_System_Threading_Thread_ConstructInternalThread (MonoThread *this)
1081 {
1082         MonoInternalThread *internal = create_internal_thread_object ();
1083
1084         internal->state = ThreadState_Unstarted;
1085         internal->apartment_state = ThreadApartmentState_Unknown;
1086         internal->managed_id = get_next_managed_thread_id ();
1087
1088         InterlockedCompareExchangePointer ((gpointer)&this->internal_thread, internal, NULL);
1089 }
1090
1091 HANDLE ves_icall_System_Threading_Thread_Thread_internal(MonoThread *this,
1092                                                          MonoObject *start)
1093 {
1094         guint32 (*start_func)(void *);
1095         struct StartInfo *start_info;
1096         HANDLE thread;
1097         gsize tid;
1098         MonoInternalThread *internal;
1099
1100         THREAD_DEBUG (g_message("%s: Trying to start a new thread: this (%p) start (%p)", __func__, this, start));
1101
1102         if (!this->internal_thread)
1103                 ves_icall_System_Threading_Thread_ConstructInternalThread (this);
1104         internal = this->internal_thread;
1105
1106         ensure_synch_cs_set (internal);
1107
1108         EnterCriticalSection (internal->synch_cs);
1109
1110         if ((internal->state & ThreadState_Unstarted) == 0) {
1111                 LeaveCriticalSection (internal->synch_cs);
1112                 mono_raise_exception (mono_get_exception_thread_state ("Thread has already been started."));
1113                 return NULL;
1114         }
1115
1116         if ((internal->state & ThreadState_Aborted) != 0) {
1117                 LeaveCriticalSection (internal->synch_cs);
1118                 return this;
1119         }
1120         start_func = NULL;
1121         {
1122                 /* This is freed in start_wrapper */
1123                 start_info = g_new0 (struct StartInfo, 1);
1124                 start_info->func = start_func;
1125                 start_info->start_arg = this->start_obj; /* FIXME: GC object stored in unmanaged memory */
1126                 start_info->delegate = start;
1127                 start_info->obj = this;
1128                 g_assert (this->obj.vtable->domain == mono_domain_get ());
1129
1130                 internal->start_notify=CreateSemaphore (NULL, 0, 0x7fffffff, NULL);
1131                 if (internal->start_notify==NULL) {
1132                         LeaveCriticalSection (internal->synch_cs);
1133                         g_warning ("%s: CreateSemaphore error 0x%x", __func__, GetLastError ());
1134                         g_free (start_info);
1135                         return(NULL);
1136                 }
1137
1138                 mono_threads_lock ();
1139                 register_thread_start_argument (this, start_info);
1140                 if (threads_starting_up == NULL) {
1141                         MONO_GC_REGISTER_ROOT_FIXED (threads_starting_up);
1142                         threads_starting_up = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_KEY_VALUE_GC);
1143                 }
1144                 mono_g_hash_table_insert (threads_starting_up, this, this);
1145                 mono_threads_unlock (); 
1146
1147                 thread=mono_create_thread(NULL, default_stacksize_for_thread (internal), (LPTHREAD_START_ROUTINE)start_wrapper, start_info,
1148                                     CREATE_SUSPENDED, &tid);
1149                 if(thread==NULL) {
1150                         LeaveCriticalSection (internal->synch_cs);
1151                         mono_threads_lock ();
1152                         mono_g_hash_table_remove (threads_starting_up, this);
1153                         mono_threads_unlock ();
1154                         g_warning("%s: CreateThread error 0x%x", __func__, GetLastError());
1155                         return(NULL);
1156                 }
1157                 
1158                 internal->handle=thread;
1159                 internal->tid=tid;
1160                 if (mono_gc_is_moving ()) {
1161                         internal->thread_pinning_ref = internal;
1162                         MONO_GC_REGISTER_ROOT_PINNING (internal->thread_pinning_ref);
1163                 }
1164                 
1165
1166                 /* Don't call handle_store() here, delay it to Start.
1167                  * We can't join a thread (trying to will just block
1168                  * forever) until it actually starts running, so don't
1169                  * store the handle till then.
1170                  */
1171
1172                 mono_thread_start (this);
1173                 
1174                 internal->state &= ~ThreadState_Unstarted;
1175
1176                 THREAD_DEBUG (g_message ("%s: Started thread ID %"G_GSIZE_FORMAT" (handle %p)", __func__, tid, thread));
1177
1178                 LeaveCriticalSection (internal->synch_cs);
1179                 return(thread);
1180         }
1181 }
1182
1183 void ves_icall_System_Threading_InternalThread_Thread_free_internal (MonoInternalThread *this, HANDLE thread)
1184 {
1185         MONO_ARCH_SAVE_REGS;
1186
1187         THREAD_DEBUG (g_message ("%s: Closing thread %p, handle %p", __func__, this, thread));
1188
1189         if (thread)
1190                 CloseHandle (thread);
1191
1192         if (this->synch_cs) {
1193                 CRITICAL_SECTION *synch_cs = this->synch_cs;
1194                 this->synch_cs = NULL;
1195                 DeleteCriticalSection (synch_cs);
1196                 g_free (synch_cs);
1197         }
1198
1199         if (this->name) {
1200                 void *name = this->name;
1201                 this->name = NULL;
1202                 g_free (name);
1203         }
1204 }
1205
1206 static void mono_thread_start (MonoThread *thread)
1207 {
1208         MonoInternalThread *internal = thread->internal_thread;
1209
1210         THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Launching thread %p (%"G_GSIZE_FORMAT")", __func__, GetCurrentThreadId (), internal, (gsize)internal->tid));
1211
1212         /* Only store the handle when the thread is about to be
1213          * launched, to avoid the main thread deadlocking while trying
1214          * to clean up a thread that will never be signalled.
1215          */
1216         if (!handle_store (thread, FALSE))
1217                 return;
1218
1219         ResumeThread (internal->handle);
1220
1221         if(internal->start_notify!=NULL) {
1222                 /* Wait for the thread to set up its TLS data etc, so
1223                  * theres no potential race condition if someone tries
1224                  * to look up the data believing the thread has
1225                  * started
1226                  */
1227
1228                 THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") waiting for thread %p (%"G_GSIZE_FORMAT") to start", __func__, GetCurrentThreadId (), internal, (gsize)internal->tid));
1229
1230                 WaitForSingleObjectEx (internal->start_notify, INFINITE, FALSE);
1231                 CloseHandle (internal->start_notify);
1232                 internal->start_notify = NULL;
1233         }
1234
1235         THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Done launching thread %p (%"G_GSIZE_FORMAT")", __func__, GetCurrentThreadId (), internal, (gsize)internal->tid));
1236 }
1237
1238 void ves_icall_System_Threading_Thread_Sleep_internal(gint32 ms)
1239 {
1240         guint32 res;
1241         MonoInternalThread *thread = mono_thread_internal_current ();
1242
1243         THREAD_DEBUG (g_message ("%s: Sleeping for %d ms", __func__, ms));
1244
1245         mono_thread_current_check_pending_interrupt ();
1246         
1247         while (TRUE) {
1248                 mono_thread_set_state (thread, ThreadState_WaitSleepJoin);
1249         
1250                 res = SleepEx(ms,TRUE);
1251         
1252                 mono_thread_clr_state (thread, ThreadState_WaitSleepJoin);
1253
1254                 if (res == WAIT_IO_COMPLETION) { /* we might have been interrupted */
1255                         MonoException* exc = mono_thread_execute_interruption (thread);
1256                         if (exc) {
1257                                 mono_raise_exception (exc);
1258                         } else {
1259                                 // FIXME: !INFINITE
1260                                 if (ms != INFINITE)
1261                                         break;
1262                         }
1263                 } else {
1264                         break;
1265                 }
1266         }
1267 }
1268
1269 void ves_icall_System_Threading_Thread_SpinWait_nop (void)
1270 {
1271 }
1272
1273 gint32
1274 ves_icall_System_Threading_Thread_GetDomainID (void) 
1275 {
1276         MONO_ARCH_SAVE_REGS;
1277
1278         return mono_domain_get()->domain_id;
1279 }
1280
1281 gboolean 
1282 ves_icall_System_Threading_Thread_Yield (void)
1283 {
1284 #ifdef HOST_WIN32
1285         return SwitchToThread ();
1286 #else
1287         return sched_yield () == 0;
1288 #endif
1289 }
1290
1291 /*
1292  * mono_thread_get_name:
1293  *
1294  *   Return the name of the thread. NAME_LEN is set to the length of the name.
1295  * Return NULL if the thread has no name. The returned memory is owned by the
1296  * caller.
1297  */
1298 gunichar2*
1299 mono_thread_get_name (MonoInternalThread *this_obj, guint32 *name_len)
1300 {
1301         gunichar2 *res;
1302
1303         ensure_synch_cs_set (this_obj);
1304         
1305         EnterCriticalSection (this_obj->synch_cs);
1306         
1307         if (!this_obj->name) {
1308                 *name_len = 0;
1309                 res = NULL;
1310         } else {
1311                 *name_len = this_obj->name_len;
1312                 res = g_new (gunichar2, this_obj->name_len);
1313                 memcpy (res, this_obj->name, sizeof (gunichar2) * this_obj->name_len);
1314         }
1315         
1316         LeaveCriticalSection (this_obj->synch_cs);
1317
1318         return res;
1319 }
1320
1321 MonoString* 
1322 ves_icall_System_Threading_Thread_GetName_internal (MonoInternalThread *this_obj)
1323 {
1324         MonoString* str;
1325
1326         ensure_synch_cs_set (this_obj);
1327         
1328         EnterCriticalSection (this_obj->synch_cs);
1329         
1330         if (!this_obj->name)
1331                 str = NULL;
1332         else
1333                 str = mono_string_new_utf16 (mono_domain_get (), this_obj->name, this_obj->name_len);
1334         
1335         LeaveCriticalSection (this_obj->synch_cs);
1336         
1337         return str;
1338 }
1339
1340 void 
1341 mono_thread_set_name_internal (MonoInternalThread *this_obj, MonoString *name, gboolean managed)
1342 {
1343         ensure_synch_cs_set (this_obj);
1344         
1345         EnterCriticalSection (this_obj->synch_cs);
1346
1347         if (this_obj->flags & MONO_THREAD_FLAG_NAME_SET) {
1348                 LeaveCriticalSection (this_obj->synch_cs);
1349                 
1350                 mono_raise_exception (mono_get_exception_invalid_operation ("Thread.Name can only be set once."));
1351                 return;
1352         }
1353         if (name) {
1354                 this_obj->name = g_new (gunichar2, mono_string_length (name));
1355                 memcpy (this_obj->name, mono_string_chars (name), mono_string_length (name) * 2);
1356                 this_obj->name_len = mono_string_length (name);
1357         }
1358         else
1359                 this_obj->name = NULL;
1360
1361         if (managed)
1362                 this_obj->flags |= MONO_THREAD_FLAG_NAME_SET;
1363         
1364         LeaveCriticalSection (this_obj->synch_cs);
1365         if (this_obj->name) {
1366                 char *tname = mono_string_to_utf8 (name);
1367                 mono_profiler_thread_name (this_obj->tid, tname);
1368                 mono_free (tname);
1369         }
1370 }
1371
1372 void 
1373 ves_icall_System_Threading_Thread_SetName_internal (MonoInternalThread *this_obj, MonoString *name)
1374 {
1375         mono_thread_set_name_internal (this_obj, name, TRUE);
1376 }
1377
1378 /* If the array is already in the requested domain, we just return it,
1379    otherwise we return a copy in that domain. */
1380 static MonoArray*
1381 byte_array_to_domain (MonoArray *arr, MonoDomain *domain)
1382 {
1383         MonoArray *copy;
1384
1385         if (!arr)
1386                 return NULL;
1387
1388         if (mono_object_domain (arr) == domain)
1389                 return arr;
1390
1391         copy = mono_array_new (domain, mono_defaults.byte_class, arr->max_length);
1392         mono_gc_memmove (mono_array_addr (copy, guint8, 0), mono_array_addr (arr, guint8, 0), arr->max_length);
1393         return copy;
1394 }
1395
1396 MonoArray*
1397 ves_icall_System_Threading_Thread_ByteArrayToRootDomain (MonoArray *arr)
1398 {
1399         return byte_array_to_domain (arr, mono_get_root_domain ());
1400 }
1401
1402 MonoArray*
1403 ves_icall_System_Threading_Thread_ByteArrayToCurrentDomain (MonoArray *arr)
1404 {
1405         return byte_array_to_domain (arr, mono_domain_get ());
1406 }
1407
1408 MonoThread *
1409 mono_thread_current (void)
1410 {
1411         MonoDomain *domain = mono_domain_get ();
1412         MonoInternalThread *internal = mono_thread_internal_current ();
1413         MonoThread **current_thread_ptr;
1414
1415         g_assert (internal);
1416         current_thread_ptr = get_current_thread_ptr_for_domain (domain, internal);
1417
1418         if (!*current_thread_ptr) {
1419                 g_assert (domain != mono_get_root_domain ());
1420                 *current_thread_ptr = new_thread_with_internal (domain, internal);
1421         }
1422         return *current_thread_ptr;
1423 }
1424
1425 MonoInternalThread*
1426 mono_thread_internal_current (void)
1427 {
1428         MonoInternalThread *res = GET_CURRENT_OBJECT ();
1429         THREAD_DEBUG (g_message ("%s: returning %p", __func__, res));
1430         return res;
1431 }
1432
1433 gboolean ves_icall_System_Threading_Thread_Join_internal(MonoInternalThread *this,
1434                                                          int ms, HANDLE thread)
1435 {
1436         MonoInternalThread *cur_thread = mono_thread_internal_current ();
1437         gboolean ret;
1438
1439         mono_thread_current_check_pending_interrupt ();
1440
1441         ensure_synch_cs_set (this);
1442         
1443         EnterCriticalSection (this->synch_cs);
1444         
1445         if ((this->state & ThreadState_Unstarted) != 0) {
1446                 LeaveCriticalSection (this->synch_cs);
1447                 
1448                 mono_raise_exception (mono_get_exception_thread_state ("Thread has not been started."));
1449                 return FALSE;
1450         }
1451
1452         LeaveCriticalSection (this->synch_cs);
1453
1454         if(ms== -1) {
1455                 ms=INFINITE;
1456         }
1457         THREAD_DEBUG (g_message ("%s: joining thread handle %p, %d ms", __func__, thread, ms));
1458         
1459         mono_thread_set_state (cur_thread, ThreadState_WaitSleepJoin);
1460
1461         ret=WaitForSingleObjectEx (thread, ms, TRUE);
1462
1463         mono_thread_clr_state (cur_thread, ThreadState_WaitSleepJoin);
1464         
1465         if(ret==WAIT_OBJECT_0) {
1466                 THREAD_DEBUG (g_message ("%s: join successful", __func__));
1467
1468                 return(TRUE);
1469         }
1470         
1471         THREAD_DEBUG (g_message ("%s: join failed", __func__));
1472
1473         return(FALSE);
1474 }
1475
1476 static gint32
1477 mono_wait_uninterrupted (MonoInternalThread *thread, gboolean multiple, guint32 numhandles, gpointer *handles, gboolean waitall, gint32 ms, gboolean alertable)
1478 {
1479         MonoException *exc;
1480         guint32 ret;
1481         gint64 start;
1482         gint32 diff_ms;
1483         gint32 wait = ms;
1484
1485         start = (ms == -1) ? 0 : mono_100ns_ticks ();
1486         do {
1487                 if (multiple)
1488                         ret = WaitForMultipleObjectsEx (numhandles, handles, waitall, wait, alertable);
1489                 else
1490                         ret = WaitForSingleObjectEx (handles [0], ms, alertable);
1491
1492                 if (ret != WAIT_IO_COMPLETION)
1493                         break;
1494
1495                 exc = mono_thread_execute_interruption (thread);
1496                 if (exc)
1497                         mono_raise_exception (exc);
1498
1499                 if (ms == -1)
1500                         continue;
1501
1502                 /* Re-calculate ms according to the time passed */
1503                 diff_ms = (mono_100ns_ticks () - start) / 10000;
1504                 if (diff_ms >= ms) {
1505                         ret = WAIT_TIMEOUT;
1506                         break;
1507                 }
1508                 wait = ms - diff_ms;
1509         } while (TRUE);
1510         
1511         return ret;
1512 }
1513
1514 /* FIXME: exitContext isnt documented */
1515 gboolean ves_icall_System_Threading_WaitHandle_WaitAll_internal(MonoArray *mono_handles, gint32 ms, gboolean exitContext)
1516 {
1517         HANDLE *handles;
1518         guint32 numhandles;
1519         guint32 ret;
1520         guint32 i;
1521         MonoObject *waitHandle;
1522         MonoInternalThread *thread = mono_thread_internal_current ();
1523
1524         /* Do this WaitSleepJoin check before creating objects */
1525         mono_thread_current_check_pending_interrupt ();
1526
1527         numhandles = mono_array_length(mono_handles);
1528         handles = g_new0(HANDLE, numhandles);
1529
1530         for(i = 0; i < numhandles; i++) {       
1531                 waitHandle = mono_array_get(mono_handles, MonoObject*, i);
1532                 handles [i] = mono_wait_handle_get_handle ((MonoWaitHandle *) waitHandle);
1533         }
1534         
1535         if(ms== -1) {
1536                 ms=INFINITE;
1537         }
1538
1539         mono_thread_set_state (thread, ThreadState_WaitSleepJoin);
1540         
1541         ret = mono_wait_uninterrupted (thread, TRUE, numhandles, handles, TRUE, ms, TRUE);
1542
1543         mono_thread_clr_state (thread, ThreadState_WaitSleepJoin);
1544
1545         g_free(handles);
1546
1547         if(ret==WAIT_FAILED) {
1548                 THREAD_WAIT_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Wait failed", __func__, GetCurrentThreadId ()));
1549                 return(FALSE);
1550         } else if(ret==WAIT_TIMEOUT) {
1551                 THREAD_WAIT_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Wait timed out", __func__, GetCurrentThreadId ()));
1552                 return(FALSE);
1553         }
1554         
1555         return(TRUE);
1556 }
1557
1558 /* FIXME: exitContext isnt documented */
1559 gint32 ves_icall_System_Threading_WaitHandle_WaitAny_internal(MonoArray *mono_handles, gint32 ms, gboolean exitContext)
1560 {
1561         HANDLE handles [MAXIMUM_WAIT_OBJECTS];
1562         guint32 numhandles;
1563         guint32 ret;
1564         guint32 i;
1565         MonoObject *waitHandle;
1566         MonoInternalThread *thread = mono_thread_internal_current ();
1567
1568         /* Do this WaitSleepJoin check before creating objects */
1569         mono_thread_current_check_pending_interrupt ();
1570
1571         numhandles = mono_array_length(mono_handles);
1572         if (numhandles > MAXIMUM_WAIT_OBJECTS)
1573                 return WAIT_FAILED;
1574
1575         for(i = 0; i < numhandles; i++) {       
1576                 waitHandle = mono_array_get(mono_handles, MonoObject*, i);
1577                 handles [i] = mono_wait_handle_get_handle ((MonoWaitHandle *) waitHandle);
1578         }
1579         
1580         if(ms== -1) {
1581                 ms=INFINITE;
1582         }
1583
1584         mono_thread_set_state (thread, ThreadState_WaitSleepJoin);
1585
1586         ret = mono_wait_uninterrupted (thread, TRUE, numhandles, handles, FALSE, ms, TRUE);
1587
1588         mono_thread_clr_state (thread, ThreadState_WaitSleepJoin);
1589
1590         THREAD_WAIT_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") returning %d", __func__, GetCurrentThreadId (), ret));
1591
1592         /*
1593          * These need to be here.  See MSDN dos on WaitForMultipleObjects.
1594          */
1595         if (ret >= WAIT_OBJECT_0 && ret <= WAIT_OBJECT_0 + numhandles - 1) {
1596                 return ret - WAIT_OBJECT_0;
1597         }
1598         else if (ret >= WAIT_ABANDONED_0 && ret <= WAIT_ABANDONED_0 + numhandles - 1) {
1599                 return ret - WAIT_ABANDONED_0;
1600         }
1601         else {
1602                 return ret;
1603         }
1604 }
1605
1606 /* FIXME: exitContext isnt documented */
1607 gboolean ves_icall_System_Threading_WaitHandle_WaitOne_internal(MonoObject *this, HANDLE handle, gint32 ms, gboolean exitContext)
1608 {
1609         guint32 ret;
1610         MonoInternalThread *thread = mono_thread_internal_current ();
1611
1612         THREAD_WAIT_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") waiting for %p, %d ms", __func__, GetCurrentThreadId (), handle, ms));
1613         
1614         if(ms== -1) {
1615                 ms=INFINITE;
1616         }
1617         
1618         mono_thread_current_check_pending_interrupt ();
1619
1620         mono_thread_set_state (thread, ThreadState_WaitSleepJoin);
1621         
1622         ret = mono_wait_uninterrupted (thread, FALSE, 1, &handle, FALSE, ms, TRUE);
1623         
1624         mono_thread_clr_state (thread, ThreadState_WaitSleepJoin);
1625         
1626         if(ret==WAIT_FAILED) {
1627                 THREAD_WAIT_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Wait failed", __func__, GetCurrentThreadId ()));
1628                 return(FALSE);
1629         } else if(ret==WAIT_TIMEOUT) {
1630                 THREAD_WAIT_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Wait timed out", __func__, GetCurrentThreadId ()));
1631                 return(FALSE);
1632         }
1633         
1634         return(TRUE);
1635 }
1636
1637 gboolean
1638 ves_icall_System_Threading_WaitHandle_SignalAndWait_Internal (HANDLE toSignal, HANDLE toWait, gint32 ms, gboolean exitContext)
1639 {
1640         guint32 ret;
1641         MonoInternalThread *thread = mono_thread_internal_current ();
1642
1643         MONO_ARCH_SAVE_REGS;
1644
1645         if (ms == -1)
1646                 ms = INFINITE;
1647
1648         mono_thread_current_check_pending_interrupt ();
1649
1650         mono_thread_set_state (thread, ThreadState_WaitSleepJoin);
1651         
1652         ret = SignalObjectAndWait (toSignal, toWait, ms, TRUE);
1653         
1654         mono_thread_clr_state (thread, ThreadState_WaitSleepJoin);
1655
1656         return  (!(ret == WAIT_TIMEOUT || ret == WAIT_IO_COMPLETION || ret == WAIT_FAILED));
1657 }
1658
1659 HANDLE ves_icall_System_Threading_Mutex_CreateMutex_internal (MonoBoolean owned, MonoString *name, MonoBoolean *created)
1660
1661         HANDLE mutex;
1662         
1663         MONO_ARCH_SAVE_REGS;
1664    
1665         *created = TRUE;
1666         
1667         if (name == NULL) {
1668                 mutex = CreateMutex (NULL, owned, NULL);
1669         } else {
1670                 mutex = CreateMutex (NULL, owned, mono_string_chars (name));
1671                 
1672                 if (GetLastError () == ERROR_ALREADY_EXISTS) {
1673                         *created = FALSE;
1674                 }
1675         }
1676
1677         return(mutex);
1678 }                                                                   
1679
1680 MonoBoolean ves_icall_System_Threading_Mutex_ReleaseMutex_internal (HANDLE handle ) { 
1681         MONO_ARCH_SAVE_REGS;
1682
1683         return(ReleaseMutex (handle));
1684 }
1685
1686 HANDLE ves_icall_System_Threading_Mutex_OpenMutex_internal (MonoString *name,
1687                                                             gint32 rights,
1688                                                             gint32 *error)
1689 {
1690         HANDLE ret;
1691         
1692         MONO_ARCH_SAVE_REGS;
1693         
1694         *error = ERROR_SUCCESS;
1695         
1696         ret = OpenMutex (rights, FALSE, mono_string_chars (name));
1697         if (ret == NULL) {
1698                 *error = GetLastError ();
1699         }
1700         
1701         return(ret);
1702 }
1703
1704
1705 HANDLE ves_icall_System_Threading_Semaphore_CreateSemaphore_internal (gint32 initialCount, gint32 maximumCount, MonoString *name, MonoBoolean *created)
1706
1707         HANDLE sem;
1708         
1709         MONO_ARCH_SAVE_REGS;
1710    
1711         *created = TRUE;
1712         
1713         if (name == NULL) {
1714                 sem = CreateSemaphore (NULL, initialCount, maximumCount, NULL);
1715         } else {
1716                 sem = CreateSemaphore (NULL, initialCount, maximumCount,
1717                                        mono_string_chars (name));
1718                 
1719                 if (GetLastError () == ERROR_ALREADY_EXISTS) {
1720                         *created = FALSE;
1721                 }
1722         }
1723
1724         return(sem);
1725 }                                                                   
1726
1727 gint32 ves_icall_System_Threading_Semaphore_ReleaseSemaphore_internal (HANDLE handle, gint32 releaseCount, MonoBoolean *fail)
1728
1729         gint32 prevcount;
1730         
1731         MONO_ARCH_SAVE_REGS;
1732
1733         *fail = !ReleaseSemaphore (handle, releaseCount, &prevcount);
1734
1735         return (prevcount);
1736 }
1737
1738 HANDLE ves_icall_System_Threading_Semaphore_OpenSemaphore_internal (MonoString *name, gint32 rights, gint32 *error)
1739 {
1740         HANDLE ret;
1741         
1742         MONO_ARCH_SAVE_REGS;
1743         
1744         *error = ERROR_SUCCESS;
1745         
1746         ret = OpenSemaphore (rights, FALSE, mono_string_chars (name));
1747         if (ret == NULL) {
1748                 *error = GetLastError ();
1749         }
1750         
1751         return(ret);
1752 }
1753
1754 HANDLE ves_icall_System_Threading_Events_CreateEvent_internal (MonoBoolean manual, MonoBoolean initial, MonoString *name, MonoBoolean *created)
1755 {
1756         HANDLE event;
1757         
1758         MONO_ARCH_SAVE_REGS;
1759
1760         *created = TRUE;
1761
1762         if (name == NULL) {
1763                 event = CreateEvent (NULL, manual, initial, NULL);
1764         } else {
1765                 event = CreateEvent (NULL, manual, initial,
1766                                      mono_string_chars (name));
1767                 
1768                 if (GetLastError () == ERROR_ALREADY_EXISTS) {
1769                         *created = FALSE;
1770                 }
1771         }
1772         
1773         return(event);
1774 }
1775
1776 gboolean ves_icall_System_Threading_Events_SetEvent_internal (HANDLE handle) {
1777         MONO_ARCH_SAVE_REGS;
1778
1779         return (SetEvent(handle));
1780 }
1781
1782 gboolean ves_icall_System_Threading_Events_ResetEvent_internal (HANDLE handle) {
1783         MONO_ARCH_SAVE_REGS;
1784
1785         return (ResetEvent(handle));
1786 }
1787
1788 void
1789 ves_icall_System_Threading_Events_CloseEvent_internal (HANDLE handle) {
1790         MONO_ARCH_SAVE_REGS;
1791
1792         CloseHandle (handle);
1793 }
1794
1795 HANDLE ves_icall_System_Threading_Events_OpenEvent_internal (MonoString *name,
1796                                                              gint32 rights,
1797                                                              gint32 *error)
1798 {
1799         HANDLE ret;
1800         
1801         MONO_ARCH_SAVE_REGS;
1802         
1803         *error = ERROR_SUCCESS;
1804         
1805         ret = OpenEvent (rights, FALSE, mono_string_chars (name));
1806         if (ret == NULL) {
1807                 *error = GetLastError ();
1808         }
1809         
1810         return(ret);
1811 }
1812
1813 gint32 ves_icall_System_Threading_Interlocked_Increment_Int (gint32 *location)
1814 {
1815         MONO_ARCH_SAVE_REGS;
1816
1817         return InterlockedIncrement (location);
1818 }
1819
1820 gint64 ves_icall_System_Threading_Interlocked_Increment_Long (gint64 *location)
1821 {
1822         gint64 ret;
1823
1824         MONO_ARCH_SAVE_REGS;
1825
1826         mono_interlocked_lock ();
1827
1828         ret = ++ *location;
1829         
1830         mono_interlocked_unlock ();
1831
1832         
1833         return ret;
1834 }
1835
1836 gint32 ves_icall_System_Threading_Interlocked_Decrement_Int (gint32 *location)
1837 {
1838         MONO_ARCH_SAVE_REGS;
1839
1840         return InterlockedDecrement(location);
1841 }
1842
1843 gint64 ves_icall_System_Threading_Interlocked_Decrement_Long (gint64 * location)
1844 {
1845         gint64 ret;
1846
1847         MONO_ARCH_SAVE_REGS;
1848
1849         mono_interlocked_lock ();
1850
1851         ret = -- *location;
1852         
1853         mono_interlocked_unlock ();
1854
1855         return ret;
1856 }
1857
1858 gint32 ves_icall_System_Threading_Interlocked_Exchange_Int (gint32 *location, gint32 value)
1859 {
1860         MONO_ARCH_SAVE_REGS;
1861
1862         return InterlockedExchange(location, value);
1863 }
1864
1865 MonoObject * ves_icall_System_Threading_Interlocked_Exchange_Object (MonoObject **location, MonoObject *value)
1866 {
1867         MonoObject *res;
1868         res = (MonoObject *) InterlockedExchangePointer((gpointer *) location, value);
1869         mono_gc_wbarrier_generic_nostore (location);
1870         return res;
1871 }
1872
1873 gpointer ves_icall_System_Threading_Interlocked_Exchange_IntPtr (gpointer *location, gpointer value)
1874 {
1875         return InterlockedExchangePointer(location, value);
1876 }
1877
1878 gfloat ves_icall_System_Threading_Interlocked_Exchange_Single (gfloat *location, gfloat value)
1879 {
1880         IntFloatUnion val, ret;
1881
1882         MONO_ARCH_SAVE_REGS;
1883
1884         val.fval = value;
1885         ret.ival = InterlockedExchange((gint32 *) location, val.ival);
1886
1887         return ret.fval;
1888 }
1889
1890 gint64 
1891 ves_icall_System_Threading_Interlocked_Exchange_Long (gint64 *location, gint64 value)
1892 {
1893 #if SIZEOF_VOID_P == 8
1894         return (gint64) InterlockedExchangePointer((gpointer *) location, (gpointer)value);
1895 #else
1896         gint64 res;
1897
1898         /* 
1899          * According to MSDN, this function is only atomic with regards to the 
1900          * other Interlocked functions on 32 bit platforms.
1901          */
1902         mono_interlocked_lock ();
1903         res = *location;
1904         *location = value;
1905         mono_interlocked_unlock ();
1906
1907         return res;
1908 #endif
1909 }
1910
1911 gdouble 
1912 ves_icall_System_Threading_Interlocked_Exchange_Double (gdouble *location, gdouble value)
1913 {
1914 #if SIZEOF_VOID_P == 8
1915         LongDoubleUnion val, ret;
1916
1917         val.fval = value;
1918         ret.ival = (gint64)InterlockedExchangePointer((gpointer *) location, (gpointer)val.ival);
1919
1920         return ret.fval;
1921 #else
1922         gdouble res;
1923
1924         /* 
1925          * According to MSDN, this function is only atomic with regards to the 
1926          * other Interlocked functions on 32 bit platforms.
1927          */
1928         mono_interlocked_lock ();
1929         res = *location;
1930         *location = value;
1931         mono_interlocked_unlock ();
1932
1933         return res;
1934 #endif
1935 }
1936
1937 gint32 ves_icall_System_Threading_Interlocked_CompareExchange_Int(gint32 *location, gint32 value, gint32 comparand)
1938 {
1939         MONO_ARCH_SAVE_REGS;
1940
1941         return InterlockedCompareExchange(location, value, comparand);
1942 }
1943
1944 MonoObject * ves_icall_System_Threading_Interlocked_CompareExchange_Object (MonoObject **location, MonoObject *value, MonoObject *comparand)
1945 {
1946         MonoObject *res;
1947         res = (MonoObject *) InterlockedCompareExchangePointer((gpointer *) location, value, comparand);
1948         mono_gc_wbarrier_generic_nostore (location);
1949         return res;
1950 }
1951
1952 gpointer ves_icall_System_Threading_Interlocked_CompareExchange_IntPtr(gpointer *location, gpointer value, gpointer comparand)
1953 {
1954         return InterlockedCompareExchangePointer(location, value, comparand);
1955 }
1956
1957 gfloat ves_icall_System_Threading_Interlocked_CompareExchange_Single (gfloat *location, gfloat value, gfloat comparand)
1958 {
1959         IntFloatUnion val, ret, cmp;
1960
1961         MONO_ARCH_SAVE_REGS;
1962
1963         val.fval = value;
1964         cmp.fval = comparand;
1965         ret.ival = InterlockedCompareExchange((gint32 *) location, val.ival, cmp.ival);
1966
1967         return ret.fval;
1968 }
1969
1970 gdouble
1971 ves_icall_System_Threading_Interlocked_CompareExchange_Double (gdouble *location, gdouble value, gdouble comparand)
1972 {
1973 #if SIZEOF_VOID_P == 8
1974         LongDoubleUnion val, comp, ret;
1975
1976         val.fval = value;
1977         comp.fval = comparand;
1978         ret.ival = (gint64)InterlockedCompareExchangePointer((gpointer *) location, (gpointer)val.ival, (gpointer)comp.ival);
1979
1980         return ret.fval;
1981 #else
1982         gdouble old;
1983
1984         mono_interlocked_lock ();
1985         old = *location;
1986         if (old == comparand)
1987                 *location = value;
1988         mono_interlocked_unlock ();
1989
1990         return old;
1991 #endif
1992 }
1993
1994 gint64 
1995 ves_icall_System_Threading_Interlocked_CompareExchange_Long (gint64 *location, gint64 value, gint64 comparand)
1996 {
1997 #if SIZEOF_VOID_P == 4
1998         if ((size_t)location & 0x7) {
1999                 gint64 old;
2000                 mono_interlocked_lock ();
2001                 old = *location;
2002                 if (old == comparand)
2003                         *location = value;
2004                 mono_interlocked_unlock ();
2005                 return old;
2006         }
2007 #endif
2008         return InterlockedCompareExchange64 (location, value, comparand);
2009 }
2010
2011 MonoObject*
2012 ves_icall_System_Threading_Interlocked_CompareExchange_T (MonoObject **location, MonoObject *value, MonoObject *comparand)
2013 {
2014         MonoObject *res;
2015         res = InterlockedCompareExchangePointer ((gpointer *)location, value, comparand);
2016         mono_gc_wbarrier_generic_nostore (location);
2017         return res;
2018 }
2019
2020 MonoObject*
2021 ves_icall_System_Threading_Interlocked_Exchange_T (MonoObject **location, MonoObject *value)
2022 {
2023         MonoObject *res;
2024         res = InterlockedExchangePointer ((gpointer *)location, value);
2025         mono_gc_wbarrier_generic_nostore (location);
2026         return res;
2027 }
2028
2029 gint32 
2030 ves_icall_System_Threading_Interlocked_Add_Int (gint32 *location, gint32 value)
2031 {
2032 #if SIZEOF_VOID_P == 8
2033         /* Should be implemented as a JIT intrinsic */
2034         mono_raise_exception (mono_get_exception_not_implemented (NULL));
2035         return 0;
2036 #else
2037         gint32 orig;
2038
2039         mono_interlocked_lock ();
2040         orig = *location;
2041         *location = orig + value;
2042         mono_interlocked_unlock ();
2043
2044         return orig + value;
2045 #endif
2046 }
2047
2048 gint64 
2049 ves_icall_System_Threading_Interlocked_Add_Long (gint64 *location, gint64 value)
2050 {
2051 #if SIZEOF_VOID_P == 8
2052         /* Should be implemented as a JIT intrinsic */
2053         mono_raise_exception (mono_get_exception_not_implemented (NULL));
2054         return 0;
2055 #else
2056         gint64 orig;
2057
2058         mono_interlocked_lock ();
2059         orig = *location;
2060         *location = orig + value;
2061         mono_interlocked_unlock ();
2062
2063         return orig + value;
2064 #endif
2065 }
2066
2067 gint64 
2068 ves_icall_System_Threading_Interlocked_Read_Long (gint64 *location)
2069 {
2070 #if SIZEOF_VOID_P == 8
2071         /* 64 bit reads are already atomic */
2072         return *location;
2073 #else
2074         gint64 res;
2075
2076         mono_interlocked_lock ();
2077         res = *location;
2078         mono_interlocked_unlock ();
2079
2080         return res;
2081 #endif
2082 }
2083
2084 void
2085 ves_icall_System_Threading_Thread_MemoryBarrier (void)
2086 {
2087         mono_threads_lock ();
2088         mono_threads_unlock ();
2089 }
2090
2091 void
2092 ves_icall_System_Threading_Thread_ClrState (MonoInternalThread* this, guint32 state)
2093 {
2094         mono_thread_clr_state (this, state);
2095
2096         if (state & ThreadState_Background) {
2097                 /* If the thread changes the background mode, the main thread has to
2098                  * be notified, since it has to rebuild the list of threads to
2099                  * wait for.
2100                  */
2101                 SetEvent (background_change_event);
2102         }
2103 }
2104
2105 void
2106 ves_icall_System_Threading_Thread_SetState (MonoInternalThread* this, guint32 state)
2107 {
2108         mono_thread_set_state (this, state);
2109         
2110         if (state & ThreadState_Background) {
2111                 /* If the thread changes the background mode, the main thread has to
2112                  * be notified, since it has to rebuild the list of threads to
2113                  * wait for.
2114                  */
2115                 SetEvent (background_change_event);
2116         }
2117 }
2118
2119 guint32
2120 ves_icall_System_Threading_Thread_GetState (MonoInternalThread* this)
2121 {
2122         guint32 state;
2123
2124         ensure_synch_cs_set (this);
2125         
2126         EnterCriticalSection (this->synch_cs);
2127         
2128         state = this->state;
2129
2130         LeaveCriticalSection (this->synch_cs);
2131         
2132         return state;
2133 }
2134
2135 void ves_icall_System_Threading_Thread_Interrupt_internal (MonoInternalThread *this)
2136 {
2137         MonoInternalThread *current;
2138         gboolean throw;
2139
2140         ensure_synch_cs_set (this);
2141
2142         current = mono_thread_internal_current ();
2143
2144         EnterCriticalSection (this->synch_cs);  
2145
2146         this->thread_interrupt_requested = TRUE;        
2147         throw = current != this && (this->state & ThreadState_WaitSleepJoin);   
2148
2149         LeaveCriticalSection (this->synch_cs);
2150         
2151         if (throw) {
2152                 abort_thread_internal (this, TRUE, FALSE);
2153         }
2154 }
2155
2156 void mono_thread_current_check_pending_interrupt ()
2157 {
2158         MonoInternalThread *thread = mono_thread_internal_current ();
2159         gboolean throw = FALSE;
2160
2161         mono_debugger_check_interruption ();
2162
2163         ensure_synch_cs_set (thread);
2164         
2165         EnterCriticalSection (thread->synch_cs);
2166         
2167         if (thread->thread_interrupt_requested) {
2168                 throw = TRUE;
2169                 thread->thread_interrupt_requested = FALSE;
2170         }
2171         
2172         LeaveCriticalSection (thread->synch_cs);
2173
2174         if (throw) {
2175                 mono_raise_exception (mono_get_exception_thread_interrupted ());
2176         }
2177 }
2178
2179 int  
2180 mono_thread_get_abort_signal (void)
2181 {
2182 #ifdef HOST_WIN32
2183         return -1;
2184 #elif defined(PLATFORM_ANDROID)
2185         return SIGUNUSED;
2186 #elif !defined (SIGRTMIN)
2187 #ifdef SIGUSR1
2188         return SIGUSR1;
2189 #else
2190         return -1;
2191 #endif /* SIGUSR1 */
2192 #else
2193         static int abort_signum = -1;
2194         int i;
2195         if (abort_signum != -1)
2196                 return abort_signum;
2197         /* we try to avoid SIGRTMIN and any one that might have been set already, see bug #75387 */
2198         for (i = SIGRTMIN + 1; i < SIGRTMAX; ++i) {
2199                 struct sigaction sinfo;
2200                 sigaction (i, NULL, &sinfo);
2201                 if (sinfo.sa_handler == SIG_DFL && (void*)sinfo.sa_sigaction == (void*)SIG_DFL) {
2202                         abort_signum = i;
2203                         return i;
2204                 }
2205         }
2206         /* fallback to the old way */
2207         return SIGRTMIN;
2208 #endif /* HOST_WIN32 */
2209 }
2210
2211 #ifdef HOST_WIN32
2212 static void CALLBACK interruption_request_apc (ULONG_PTR param)
2213 {
2214         MonoException* exc = mono_thread_request_interruption (FALSE);
2215         if (exc) mono_raise_exception (exc);
2216 }
2217 #endif /* HOST_WIN32 */
2218
2219 /*
2220  * signal_thread_state_change
2221  *
2222  * Tells the thread that his state has changed and it has to enter the new
2223  * state as soon as possible.
2224  */
2225 static void signal_thread_state_change (MonoInternalThread *thread)
2226 {
2227         if (thread == mono_thread_internal_current ()) {
2228                 /* Do it synchronously */
2229                 MonoException *exc = mono_thread_request_interruption (FALSE); 
2230                 if (exc)
2231                         mono_raise_exception (exc);
2232         }
2233
2234 #ifdef HOST_WIN32
2235         QueueUserAPC ((PAPCFUNC)interruption_request_apc, thread->handle, NULL);
2236 #else
2237         /* fixme: store the state somewhere */
2238         mono_thread_kill (thread, mono_thread_get_abort_signal ());
2239
2240         /* 
2241          * This will cause waits to be broken.
2242          * It will also prevent the thread from entering a wait, so if the thread returns
2243          * from the wait before it receives the abort signal, it will just spin in the wait
2244          * functions in the io-layer until the signal handler calls QueueUserAPC which will
2245          * make it return.
2246          */
2247         wapi_interrupt_thread (thread->handle);
2248 #endif /* HOST_WIN32 */
2249 }
2250
2251 void
2252 ves_icall_System_Threading_Thread_Abort (MonoInternalThread *thread, MonoObject *state)
2253 {
2254         ensure_synch_cs_set (thread);
2255         
2256         EnterCriticalSection (thread->synch_cs);
2257         
2258         if ((thread->state & ThreadState_AbortRequested) != 0 || 
2259                 (thread->state & ThreadState_StopRequested) != 0 ||
2260                 (thread->state & ThreadState_Stopped) != 0)
2261         {
2262                 LeaveCriticalSection (thread->synch_cs);
2263                 return;
2264         }
2265
2266         if ((thread->state & ThreadState_Unstarted) != 0) {
2267                 thread->state |= ThreadState_Aborted;
2268                 LeaveCriticalSection (thread->synch_cs);
2269                 return;
2270         }
2271
2272         thread->state |= ThreadState_AbortRequested;
2273         if (thread->abort_state_handle)
2274                 mono_gchandle_free (thread->abort_state_handle);
2275         if (state) {
2276                 thread->abort_state_handle = mono_gchandle_new (state, FALSE);
2277                 g_assert (thread->abort_state_handle);
2278         } else {
2279                 thread->abort_state_handle = 0;
2280         }
2281         thread->abort_exc = NULL;
2282
2283         /*
2284          * abort_exc is set in mono_thread_execute_interruption(),
2285          * triggered by the call to signal_thread_state_change(),
2286          * below.  There's a point between where we have
2287          * abort_state_handle set, but abort_exc NULL, but that's not
2288          * a problem.
2289          */
2290
2291         LeaveCriticalSection (thread->synch_cs);
2292
2293         THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Abort requested for %p (%"G_GSIZE_FORMAT")", __func__, GetCurrentThreadId (), thread, (gsize)thread->tid));
2294
2295         /* During shutdown, we can't wait for other threads */
2296         if (!shutting_down)
2297                 /* Make sure the thread is awake */
2298                 mono_thread_resume (thread);
2299         
2300         abort_thread_internal (thread, TRUE, TRUE);
2301 }
2302
2303 void
2304 ves_icall_System_Threading_Thread_ResetAbort (void)
2305 {
2306         MonoInternalThread *thread = mono_thread_internal_current ();
2307         gboolean was_aborting;
2308
2309         ensure_synch_cs_set (thread);
2310         
2311         EnterCriticalSection (thread->synch_cs);
2312         was_aborting = thread->state & ThreadState_AbortRequested;
2313         thread->state &= ~ThreadState_AbortRequested;
2314         LeaveCriticalSection (thread->synch_cs);
2315
2316         if (!was_aborting) {
2317                 const char *msg = "Unable to reset abort because no abort was requested";
2318                 mono_raise_exception (mono_get_exception_thread_state (msg));
2319         }
2320         thread->abort_exc = NULL;
2321         if (thread->abort_state_handle) {
2322                 mono_gchandle_free (thread->abort_state_handle);
2323                 /* This is actually not necessary - the handle
2324                    only counts if the exception is set */
2325                 thread->abort_state_handle = 0;
2326         }
2327 }
2328
2329 void
2330 mono_thread_internal_reset_abort (MonoInternalThread *thread)
2331 {
2332         ensure_synch_cs_set (thread);
2333
2334         EnterCriticalSection (thread->synch_cs);
2335
2336         thread->state &= ~ThreadState_AbortRequested;
2337
2338         if (thread->abort_exc) {
2339                 thread->abort_exc = NULL;
2340                 if (thread->abort_state_handle) {
2341                         mono_gchandle_free (thread->abort_state_handle);
2342                         /* This is actually not necessary - the handle
2343                            only counts if the exception is set */
2344                         thread->abort_state_handle = 0;
2345                 }
2346         }
2347
2348         LeaveCriticalSection (thread->synch_cs);
2349 }
2350
2351 MonoObject*
2352 ves_icall_System_Threading_Thread_GetAbortExceptionState (MonoThread *this)
2353 {
2354         MonoInternalThread *thread = this->internal_thread;
2355         MonoObject *state, *deserialized = NULL, *exc;
2356         MonoDomain *domain;
2357
2358         if (!thread->abort_state_handle)
2359                 return NULL;
2360
2361         state = mono_gchandle_get_target (thread->abort_state_handle);
2362         g_assert (state);
2363
2364         domain = mono_domain_get ();
2365         if (mono_object_domain (state) == domain)
2366                 return state;
2367
2368         deserialized = mono_object_xdomain_representation (state, domain, &exc);
2369
2370         if (!deserialized) {
2371                 MonoException *invalid_op_exc = mono_get_exception_invalid_operation ("Thread.ExceptionState cannot access an ExceptionState from a different AppDomain");
2372                 if (exc)
2373                         MONO_OBJECT_SETREF (invalid_op_exc, inner_ex, exc);
2374                 mono_raise_exception (invalid_op_exc);
2375         }
2376
2377         return deserialized;
2378 }
2379
2380 static gboolean
2381 mono_thread_suspend (MonoInternalThread *thread)
2382 {
2383         ensure_synch_cs_set (thread);
2384         
2385         EnterCriticalSection (thread->synch_cs);
2386
2387         if ((thread->state & ThreadState_Unstarted) != 0 || 
2388                 (thread->state & ThreadState_Aborted) != 0 || 
2389                 (thread->state & ThreadState_Stopped) != 0)
2390         {
2391                 LeaveCriticalSection (thread->synch_cs);
2392                 return FALSE;
2393         }
2394
2395         if ((thread->state & ThreadState_Suspended) != 0 || 
2396                 (thread->state & ThreadState_SuspendRequested) != 0 ||
2397                 (thread->state & ThreadState_StopRequested) != 0) 
2398         {
2399                 LeaveCriticalSection (thread->synch_cs);
2400                 return TRUE;
2401         }
2402         
2403         thread->state |= ThreadState_SuspendRequested;
2404
2405         LeaveCriticalSection (thread->synch_cs);
2406
2407         suspend_thread_internal (thread, FALSE);
2408         return TRUE;
2409 }
2410
2411 void
2412 ves_icall_System_Threading_Thread_Suspend (MonoInternalThread *thread)
2413 {
2414         if (!mono_thread_suspend (thread))
2415                 mono_raise_exception (mono_get_exception_thread_state ("Thread has not been started, or is dead."));
2416 }
2417
2418 static gboolean
2419 mono_thread_resume (MonoInternalThread *thread)
2420 {
2421         ensure_synch_cs_set (thread);
2422         
2423         EnterCriticalSection (thread->synch_cs);
2424
2425         if ((thread->state & ThreadState_SuspendRequested) != 0) {
2426                 thread->state &= ~ThreadState_SuspendRequested;
2427                 LeaveCriticalSection (thread->synch_cs);
2428                 return TRUE;
2429         }
2430
2431         if ((thread->state & ThreadState_Suspended) == 0 ||
2432                 (thread->state & ThreadState_Unstarted) != 0 || 
2433                 (thread->state & ThreadState_Aborted) != 0 || 
2434                 (thread->state & ThreadState_Stopped) != 0)
2435         {
2436                 LeaveCriticalSection (thread->synch_cs);
2437                 return FALSE;
2438         }
2439
2440         return resume_thread_internal (thread);
2441 }
2442
2443 void
2444 ves_icall_System_Threading_Thread_Resume (MonoThread *thread)
2445 {
2446         if (!thread->internal_thread || !mono_thread_resume (thread->internal_thread))
2447                 mono_raise_exception (mono_get_exception_thread_state ("Thread has not been started, or is dead."));
2448 }
2449
2450 static gboolean
2451 mono_threads_is_critical_method (MonoMethod *method)
2452 {
2453         switch (method->wrapper_type) {
2454         case MONO_WRAPPER_RUNTIME_INVOKE:
2455         case MONO_WRAPPER_XDOMAIN_INVOKE:
2456         case MONO_WRAPPER_XDOMAIN_DISPATCH:     
2457                 return TRUE;
2458         }
2459         return FALSE;
2460 }
2461
2462 static gboolean
2463 find_wrapper (MonoMethod *m, gint no, gint ilo, gboolean managed, gpointer data)
2464 {
2465         if (managed)
2466                 return TRUE;
2467
2468         if (mono_threads_is_critical_method (m)) {
2469                 *((gboolean*)data) = TRUE;
2470                 return TRUE;
2471         }
2472         return FALSE;
2473 }
2474
2475 static gboolean 
2476 is_running_protected_wrapper (void)
2477 {
2478         gboolean found = FALSE;
2479         mono_stack_walk (find_wrapper, &found);
2480         return found;
2481 }
2482
2483 void mono_thread_internal_stop (MonoInternalThread *thread)
2484 {
2485         ensure_synch_cs_set (thread);
2486         
2487         EnterCriticalSection (thread->synch_cs);
2488
2489         if ((thread->state & ThreadState_StopRequested) != 0 ||
2490                 (thread->state & ThreadState_Stopped) != 0)
2491         {
2492                 LeaveCriticalSection (thread->synch_cs);
2493                 return;
2494         }
2495         
2496         /* Make sure the thread is awake */
2497         mono_thread_resume (thread);
2498
2499         thread->state |= ThreadState_StopRequested;
2500         thread->state &= ~ThreadState_AbortRequested;
2501         
2502         LeaveCriticalSection (thread->synch_cs);
2503         
2504         abort_thread_internal (thread, TRUE, TRUE);
2505 }
2506
2507 void mono_thread_stop (MonoThread *thread)
2508 {
2509         mono_thread_internal_stop (thread->internal_thread);
2510 }
2511
2512 gint8
2513 ves_icall_System_Threading_Thread_VolatileRead1 (void *ptr)
2514 {
2515         return *((volatile gint8 *) (ptr));
2516 }
2517
2518 gint16
2519 ves_icall_System_Threading_Thread_VolatileRead2 (void *ptr)
2520 {
2521         return *((volatile gint16 *) (ptr));
2522 }
2523
2524 gint32
2525 ves_icall_System_Threading_Thread_VolatileRead4 (void *ptr)
2526 {
2527         return *((volatile gint32 *) (ptr));
2528 }
2529
2530 gint64
2531 ves_icall_System_Threading_Thread_VolatileRead8 (void *ptr)
2532 {
2533 #if SIZEOF_VOID_P == 8
2534         return *((volatile gint64 *) (ptr));
2535 #else
2536         if ((size_t)ptr & 0x7) {
2537                 gint64 value;
2538                 mono_interlocked_lock ();
2539                 value = *(gint64 *)ptr;
2540                 mono_interlocked_unlock ();
2541                 return value;
2542         }
2543         return InterlockedCompareExchange64 (ptr, 0, 0); /*Must ensure atomicity of the operation. */
2544 #endif
2545 }
2546
2547 void *
2548 ves_icall_System_Threading_Thread_VolatileReadIntPtr (void *ptr)
2549 {
2550         return (void *)  *((volatile void **) ptr);
2551 }
2552
2553 double
2554 ves_icall_System_Threading_Thread_VolatileReadDouble (void *ptr)
2555 {
2556         return *((volatile double *) (ptr));
2557 }
2558
2559 float
2560 ves_icall_System_Threading_Thread_VolatileReadFloat (void *ptr)
2561 {
2562         return *((volatile float *) (ptr));
2563 }
2564
2565 MonoObject*
2566 ves_icall_System_Threading_Volatile_Read_T (void *ptr)
2567 {
2568         return (MonoObject*)*((volatile MonoObject**)ptr);
2569 }
2570
2571 void
2572 ves_icall_System_Threading_Thread_VolatileWrite1 (void *ptr, gint8 value)
2573 {
2574         *((volatile gint8 *) ptr) = value;
2575 }
2576
2577 void
2578 ves_icall_System_Threading_Thread_VolatileWrite2 (void *ptr, gint16 value)
2579 {
2580         *((volatile gint16 *) ptr) = value;
2581 }
2582
2583 void
2584 ves_icall_System_Threading_Thread_VolatileWrite4 (void *ptr, gint32 value)
2585 {
2586         *((volatile gint32 *) ptr) = value;
2587 }
2588
2589 void
2590 ves_icall_System_Threading_Thread_VolatileWrite8 (void *ptr, gint64 value)
2591 {
2592         *((volatile gint64 *) ptr) = value;
2593 }
2594
2595 void
2596 ves_icall_System_Threading_Thread_VolatileWriteIntPtr (void *ptr, void *value)
2597 {
2598         *((volatile void **) ptr) = value;
2599 }
2600
2601 void
2602 ves_icall_System_Threading_Thread_VolatileWriteObject (void *ptr, void *value)
2603 {
2604         mono_gc_wbarrier_generic_store (ptr, value);
2605 }
2606
2607 void
2608 ves_icall_System_Threading_Thread_VolatileWriteDouble (void *ptr, double value)
2609 {
2610         *((volatile double *) ptr) = value;
2611 }
2612
2613 void
2614 ves_icall_System_Threading_Thread_VolatileWriteFloat (void *ptr, float value)
2615 {
2616         *((volatile float *) ptr) = value;
2617 }
2618
2619 void
2620 ves_icall_System_Threading_Volatile_Write_T (void *ptr, MonoObject *value)
2621 {
2622         *((volatile MonoObject **) ptr) = value;
2623         mono_gc_wbarrier_generic_nostore (ptr);
2624 }
2625
2626 void
2627 mono_thread_init_tls (void)
2628 {
2629         MONO_FAST_TLS_INIT (tls_current_object);
2630         mono_native_tls_alloc (&current_object_key, NULL);
2631 }
2632
2633 void mono_thread_init (MonoThreadStartCB start_cb,
2634                        MonoThreadAttachCB attach_cb)
2635 {
2636         InitializeCriticalSection(&threads_mutex);
2637         InitializeCriticalSection(&interlocked_mutex);
2638         InitializeCriticalSection(&contexts_mutex);
2639         
2640         background_change_event = CreateEvent (NULL, TRUE, FALSE, NULL);
2641         g_assert(background_change_event != NULL);
2642         
2643         mono_init_static_data_info (&thread_static_info);
2644         mono_init_static_data_info (&context_static_info);
2645
2646         THREAD_DEBUG (g_message ("%s: Allocated current_object_key %d", __func__, current_object_key));
2647
2648         mono_thread_start_cb = start_cb;
2649         mono_thread_attach_cb = attach_cb;
2650
2651         /* Get a pseudo handle to the current process.  This is just a
2652          * kludge so that wapi can build a process handle if needed.
2653          * As a pseudo handle is returned, we don't need to clean
2654          * anything up.
2655          */
2656         GetCurrentProcess ();
2657 }
2658
2659 void mono_thread_cleanup (void)
2660 {
2661 #if !defined(HOST_WIN32) && !defined(RUN_IN_SUBTHREAD)
2662         /* The main thread must abandon any held mutexes (particularly
2663          * important for named mutexes as they are shared across
2664          * processes, see bug 74680.)  This will happen when the
2665          * thread exits, but if it's not running in a subthread it
2666          * won't exit in time.
2667          */
2668         /* Using non-w32 API is a nasty kludge, but I couldn't find
2669          * anything in the documentation that would let me do this
2670          * here yet still be safe to call on windows.
2671          */
2672         _wapi_thread_signal_self (mono_environment_exitcode_get ());
2673 #endif
2674
2675 #if 0
2676         /* This stuff needs more testing, it seems one of these
2677          * critical sections can be locked when mono_thread_cleanup is
2678          * called.
2679          */
2680         DeleteCriticalSection (&threads_mutex);
2681         DeleteCriticalSection (&interlocked_mutex);
2682         DeleteCriticalSection (&contexts_mutex);
2683         DeleteCriticalSection (&delayed_free_table_mutex);
2684         DeleteCriticalSection (&small_id_mutex);
2685         CloseHandle (background_change_event);
2686 #endif
2687
2688         mono_native_tls_free (current_object_key);
2689 }
2690
2691 void
2692 mono_threads_install_cleanup (MonoThreadCleanupFunc func)
2693 {
2694         mono_thread_cleanup_fn = func;
2695 }
2696
2697 void
2698 mono_thread_set_manage_callback (MonoThread *thread, MonoThreadManageCallback func)
2699 {
2700         thread->internal_thread->manage_callback = func;
2701 }
2702
2703 void mono_threads_install_notify_pending_exc (MonoThreadNotifyPendingExcFunc func)
2704 {
2705         mono_thread_notify_pending_exc_fn = func;
2706 }
2707
2708 G_GNUC_UNUSED
2709 static void print_tids (gpointer key, gpointer value, gpointer user)
2710 {
2711         /* GPOINTER_TO_UINT breaks horribly if sizeof(void *) >
2712          * sizeof(uint) and a cast to uint would overflow
2713          */
2714         /* Older versions of glib don't have G_GSIZE_FORMAT, so just
2715          * print this as a pointer.
2716          */
2717         g_message ("Waiting for: %p", key);
2718 }
2719
2720 struct wait_data 
2721 {
2722         HANDLE handles[MAXIMUM_WAIT_OBJECTS];
2723         MonoInternalThread *threads[MAXIMUM_WAIT_OBJECTS];
2724         guint32 num;
2725 };
2726
2727 static void wait_for_tids (struct wait_data *wait, guint32 timeout)
2728 {
2729         guint32 i, ret;
2730         
2731         THREAD_DEBUG (g_message("%s: %d threads to wait for in this batch", __func__, wait->num));
2732
2733         ret=WaitForMultipleObjectsEx(wait->num, wait->handles, TRUE, timeout, TRUE);
2734
2735         if(ret==WAIT_FAILED) {
2736                 /* See the comment in build_wait_tids() */
2737                 THREAD_DEBUG (g_message ("%s: Wait failed", __func__));
2738                 return;
2739         }
2740         
2741         for(i=0; i<wait->num; i++)
2742                 CloseHandle (wait->handles[i]);
2743
2744         if (ret == WAIT_TIMEOUT)
2745                 return;
2746
2747         for(i=0; i<wait->num; i++) {
2748                 gsize tid = wait->threads[i]->tid;
2749                 
2750                 mono_threads_lock ();
2751                 if(mono_g_hash_table_lookup (threads, (gpointer)tid)!=NULL) {
2752                         /* This thread must have been killed, because
2753                          * it hasn't cleaned itself up. (It's just
2754                          * possible that the thread exited before the
2755                          * parent thread had a chance to store the
2756                          * handle, and now there is another pointer to
2757                          * the already-exited thread stored.  In this
2758                          * case, we'll just get two
2759                          * mono_profiler_thread_end() calls for the
2760                          * same thread.)
2761                          */
2762         
2763                         mono_threads_unlock ();
2764                         THREAD_DEBUG (g_message ("%s: cleaning up after thread %p (%"G_GSIZE_FORMAT")", __func__, wait->threads[i], tid));
2765                         thread_cleanup (wait->threads[i]);
2766                 } else {
2767                         mono_threads_unlock ();
2768                 }
2769         }
2770 }
2771
2772 static void wait_for_tids_or_state_change (struct wait_data *wait, guint32 timeout)
2773 {
2774         guint32 i, ret, count;
2775         
2776         THREAD_DEBUG (g_message("%s: %d threads to wait for in this batch", __func__, wait->num));
2777
2778         /* Add the thread state change event, so it wakes up if a thread changes
2779          * to background mode.
2780          */
2781         count = wait->num;
2782         if (count < MAXIMUM_WAIT_OBJECTS) {
2783                 wait->handles [count] = background_change_event;
2784                 count++;
2785         }
2786
2787         ret=WaitForMultipleObjectsEx (count, wait->handles, FALSE, timeout, TRUE);
2788
2789         if(ret==WAIT_FAILED) {
2790                 /* See the comment in build_wait_tids() */
2791                 THREAD_DEBUG (g_message ("%s: Wait failed", __func__));
2792                 return;
2793         }
2794         
2795         for(i=0; i<wait->num; i++)
2796                 CloseHandle (wait->handles[i]);
2797
2798         if (ret == WAIT_TIMEOUT)
2799                 return;
2800         
2801         if (ret < wait->num) {
2802                 gsize tid = wait->threads[ret]->tid;
2803                 mono_threads_lock ();
2804                 if (mono_g_hash_table_lookup (threads, (gpointer)tid)!=NULL) {
2805                         /* See comment in wait_for_tids about thread cleanup */
2806                         mono_threads_unlock ();
2807                         THREAD_DEBUG (g_message ("%s: cleaning up after thread %"G_GSIZE_FORMAT, __func__, tid));
2808                         thread_cleanup (wait->threads [ret]);
2809                 } else
2810                         mono_threads_unlock ();
2811         }
2812 }
2813
2814 static void build_wait_tids (gpointer key, gpointer value, gpointer user)
2815 {
2816         struct wait_data *wait=(struct wait_data *)user;
2817
2818         if(wait->num<MAXIMUM_WAIT_OBJECTS) {
2819                 HANDLE handle;
2820                 MonoInternalThread *thread=(MonoInternalThread *)value;
2821
2822                 /* Ignore background threads, we abort them later */
2823                 /* Do not lock here since it is not needed and the caller holds threads_lock */
2824                 if (thread->state & ThreadState_Background) {
2825                         THREAD_DEBUG (g_message ("%s: ignoring background thread %"G_GSIZE_FORMAT, __func__, (gsize)thread->tid));
2826                         return; /* just leave, ignore */
2827                 }
2828                 
2829                 if (mono_gc_is_finalizer_internal_thread (thread)) {
2830                         THREAD_DEBUG (g_message ("%s: ignoring finalizer thread %"G_GSIZE_FORMAT, __func__, (gsize)thread->tid));
2831                         return;
2832                 }
2833
2834                 if (thread == mono_thread_internal_current ()) {
2835                         THREAD_DEBUG (g_message ("%s: ignoring current thread %"G_GSIZE_FORMAT, __func__, (gsize)thread->tid));
2836                         return;
2837                 }
2838
2839                 if (mono_thread_get_main () && (thread == mono_thread_get_main ()->internal_thread)) {
2840                         THREAD_DEBUG (g_message ("%s: ignoring main thread %"G_GSIZE_FORMAT, __func__, (gsize)thread->tid));
2841                         return;
2842                 }
2843
2844                 if (thread->flags & MONO_THREAD_FLAG_DONT_MANAGE) {
2845                         THREAD_DEBUG (g_message ("%s: ignoring thread %" G_GSIZE_FORMAT "with DONT_MANAGE flag set.", __func__, (gsize)thread->tid));
2846                         return;
2847                 }
2848
2849                 handle = OpenThread (THREAD_ALL_ACCESS, TRUE, thread->tid);
2850                 if (handle == NULL) {
2851                         THREAD_DEBUG (g_message ("%s: ignoring unopenable thread %"G_GSIZE_FORMAT, __func__, (gsize)thread->tid));
2852                         return;
2853                 }
2854                 
2855                 THREAD_DEBUG (g_message ("%s: Invoking mono_thread_manage callback on thread %p", __func__, thread));
2856                 if ((thread->manage_callback == NULL) || (thread->manage_callback (thread->root_domain_thread) == TRUE)) {
2857                         wait->handles[wait->num]=handle;
2858                         wait->threads[wait->num]=thread;
2859                         wait->num++;
2860
2861                         THREAD_DEBUG (g_message ("%s: adding thread %"G_GSIZE_FORMAT, __func__, (gsize)thread->tid));
2862                 } else {
2863                         THREAD_DEBUG (g_message ("%s: ignoring (because of callback) thread %"G_GSIZE_FORMAT, __func__, (gsize)thread->tid));
2864                 }
2865                 
2866                 
2867         } else {
2868                 /* Just ignore the rest, we can't do anything with
2869                  * them yet
2870                  */
2871         }
2872 }
2873
2874 static gboolean
2875 remove_and_abort_threads (gpointer key, gpointer value, gpointer user)
2876 {
2877         struct wait_data *wait=(struct wait_data *)user;
2878         gsize self = GetCurrentThreadId ();
2879         MonoInternalThread *thread = value;
2880         HANDLE handle;
2881
2882         if (wait->num >= MAXIMUM_WAIT_OBJECTS)
2883                 return FALSE;
2884
2885         /* The finalizer thread is not a background thread */
2886         if (thread->tid != self && (thread->state & ThreadState_Background) != 0 &&
2887                 !(thread->flags & MONO_THREAD_FLAG_DONT_MANAGE)) {
2888         
2889                 handle = OpenThread (THREAD_ALL_ACCESS, TRUE, thread->tid);
2890                 if (handle == NULL)
2891                         return FALSE;
2892
2893                 /* printf ("A: %d\n", wait->num); */
2894                 wait->handles[wait->num]=thread->handle;
2895                 wait->threads[wait->num]=thread;
2896                 wait->num++;
2897
2898                 THREAD_DEBUG (g_print ("%s: Aborting id: %"G_GSIZE_FORMAT"\n", __func__, (gsize)thread->tid));
2899                 mono_thread_internal_stop (thread);
2900                 return TRUE;
2901         }
2902
2903         return (thread->tid != self && !mono_gc_is_finalizer_internal_thread (thread)); 
2904 }
2905
2906 /** 
2907  * mono_threads_set_shutting_down:
2908  *
2909  * Is called by a thread that wants to shut down Mono. If the runtime is already
2910  * shutting down, the calling thread is suspended/stopped, and this function never
2911  * returns.
2912  */
2913 void
2914 mono_threads_set_shutting_down (void)
2915 {
2916         MonoInternalThread *current_thread = mono_thread_internal_current ();
2917
2918         mono_threads_lock ();
2919
2920         if (shutting_down) {
2921                 mono_threads_unlock ();
2922
2923                 /* Make sure we're properly suspended/stopped */
2924
2925                 EnterCriticalSection (current_thread->synch_cs);
2926
2927                 if ((current_thread->state & ThreadState_SuspendRequested) ||
2928                     (current_thread->state & ThreadState_AbortRequested) ||
2929                     (current_thread->state & ThreadState_StopRequested)) {
2930                         LeaveCriticalSection (current_thread->synch_cs);
2931                         mono_thread_execute_interruption (current_thread);
2932                 } else {
2933                         current_thread->state |= ThreadState_Stopped;
2934                         LeaveCriticalSection (current_thread->synch_cs);
2935                 }
2936
2937                 /*since we're killing the thread, unset the current domain.*/
2938                 mono_domain_unset ();
2939
2940                 /* Wake up other threads potentially waiting for us */
2941                 ExitThread (0);
2942         } else {
2943                 shutting_down = TRUE;
2944
2945                 /* Not really a background state change, but this will
2946                  * interrupt the main thread if it is waiting for all
2947                  * the other threads.
2948                  */
2949                 SetEvent (background_change_event);
2950                 
2951                 mono_threads_unlock ();
2952         }
2953 }
2954
2955 void mono_thread_manage (void)
2956 {
2957         struct wait_data wait_data;
2958         struct wait_data *wait = &wait_data;
2959
2960         memset (wait, 0, sizeof (struct wait_data));
2961         /* join each thread that's still running */
2962         THREAD_DEBUG (g_message ("%s: Joining each running thread...", __func__));
2963         
2964         mono_threads_lock ();
2965         if(threads==NULL) {
2966                 THREAD_DEBUG (g_message("%s: No threads", __func__));
2967                 mono_threads_unlock ();
2968                 return;
2969         }
2970         mono_threads_unlock ();
2971         
2972         do {
2973                 mono_threads_lock ();
2974                 if (shutting_down) {
2975                         /* somebody else is shutting down */
2976                         mono_threads_unlock ();
2977                         break;
2978                 }
2979                 THREAD_DEBUG (g_message ("%s: There are %d threads to join", __func__, mono_g_hash_table_size (threads));
2980                         mono_g_hash_table_foreach (threads, print_tids, NULL));
2981         
2982                 ResetEvent (background_change_event);
2983                 wait->num=0;
2984                 /*We must zero all InternalThread pointers to avoid making the GC unhappy.*/
2985                 memset (wait->threads, 0, MAXIMUM_WAIT_OBJECTS * SIZEOF_VOID_P);
2986                 mono_g_hash_table_foreach (threads, build_wait_tids, wait);
2987                 mono_threads_unlock ();
2988                 if(wait->num>0) {
2989                         /* Something to wait for */
2990                         wait_for_tids_or_state_change (wait, INFINITE);
2991                 }
2992                 THREAD_DEBUG (g_message ("%s: I have %d threads after waiting.", __func__, wait->num));
2993         } while(wait->num>0);
2994
2995         /* Mono is shutting down, so just wait for the end */
2996         if (!mono_runtime_try_shutdown ()) {
2997                 /*FIXME mono_thread_suspend probably should call mono_thread_execute_interruption when self interrupting. */
2998                 mono_thread_suspend (mono_thread_internal_current ());
2999                 mono_thread_execute_interruption (mono_thread_internal_current ());
3000         }
3001
3002         /* 
3003          * Remove everything but the finalizer thread and self.
3004          * Also abort all the background threads
3005          * */
3006         do {
3007                 mono_threads_lock ();
3008
3009                 wait->num = 0;
3010                 /*We must zero all InternalThread pointers to avoid making the GC unhappy.*/
3011                 memset (wait->threads, 0, MAXIMUM_WAIT_OBJECTS * SIZEOF_VOID_P);
3012                 mono_g_hash_table_foreach_remove (threads, remove_and_abort_threads, wait);
3013
3014                 mono_threads_unlock ();
3015
3016                 THREAD_DEBUG (g_message ("%s: wait->num is now %d", __func__, wait->num));
3017                 if(wait->num>0) {
3018                         /* Something to wait for */
3019                         wait_for_tids (wait, INFINITE);
3020                 }
3021         } while (wait->num > 0);
3022         
3023         /* 
3024          * give the subthreads a chance to really quit (this is mainly needed
3025          * to get correct user and system times from getrusage/wait/time(1)).
3026          * This could be removed if we avoid pthread_detach() and use pthread_join().
3027          */
3028 #ifndef HOST_WIN32
3029         sched_yield ();
3030 #endif
3031 }
3032
3033 static void terminate_thread (gpointer key, gpointer value, gpointer user)
3034 {
3035         MonoInternalThread *thread=(MonoInternalThread *)value;
3036         
3037         if(thread->tid != (gsize)user) {
3038                 /*TerminateThread (thread->handle, -1);*/
3039         }
3040 }
3041
3042 void mono_thread_abort_all_other_threads (void)
3043 {
3044         gsize self = GetCurrentThreadId ();
3045
3046         mono_threads_lock ();
3047         THREAD_DEBUG (g_message ("%s: There are %d threads to abort", __func__,
3048                                  mono_g_hash_table_size (threads));
3049                       mono_g_hash_table_foreach (threads, print_tids, NULL));
3050
3051         mono_g_hash_table_foreach (threads, terminate_thread, (gpointer)self);
3052         
3053         mono_threads_unlock ();
3054 }
3055
3056 static void
3057 collect_threads_for_suspend (gpointer key, gpointer value, gpointer user_data)
3058 {
3059         MonoInternalThread *thread = (MonoInternalThread*)value;
3060         struct wait_data *wait = (struct wait_data*)user_data;
3061         HANDLE handle;
3062
3063         /* 
3064          * We try to exclude threads early, to avoid running into the MAXIMUM_WAIT_OBJECTS
3065          * limitation.
3066          * This needs no locking.
3067          */
3068         if ((thread->state & ThreadState_Suspended) != 0 || 
3069                 (thread->state & ThreadState_Stopped) != 0)
3070                 return;
3071
3072         if (wait->num<MAXIMUM_WAIT_OBJECTS) {
3073                 handle = OpenThread (THREAD_ALL_ACCESS, TRUE, thread->tid);
3074                 if (handle == NULL)
3075                         return;
3076
3077                 wait->handles [wait->num] = handle;
3078                 wait->threads [wait->num] = thread;
3079                 wait->num++;
3080         }
3081 }
3082
3083 /*
3084  * mono_thread_suspend_all_other_threads:
3085  *
3086  *  Suspend all managed threads except the finalizer thread and this thread. It is
3087  * not possible to resume them later.
3088  */
3089 void mono_thread_suspend_all_other_threads (void)
3090 {
3091         struct wait_data wait_data;
3092         struct wait_data *wait = &wait_data;
3093         int i;
3094         gsize self = GetCurrentThreadId ();
3095         gpointer *events;
3096         guint32 eventidx = 0;
3097         gboolean starting, finished;
3098
3099         memset (wait, 0, sizeof (struct wait_data));
3100         /*
3101          * The other threads could be in an arbitrary state at this point, i.e.
3102          * they could be starting up, shutting down etc. This means that there could be
3103          * threads which are not even in the threads hash table yet.
3104          */
3105
3106         /* 
3107          * First we set a barrier which will be checked by all threads before they
3108          * are added to the threads hash table, and they will exit if the flag is set.
3109          * This ensures that no threads could be added to the hash later.
3110          * We will use shutting_down as the barrier for now.
3111          */
3112         g_assert (shutting_down);
3113
3114         /*
3115          * We make multiple calls to WaitForMultipleObjects since:
3116          * - we can only wait for MAXIMUM_WAIT_OBJECTS threads
3117          * - some threads could exit without becoming suspended
3118          */
3119         finished = FALSE;
3120         while (!finished) {
3121                 /*
3122                  * Make a copy of the hashtable since we can't do anything with
3123                  * threads while threads_mutex is held.
3124                  */
3125                 wait->num = 0;
3126                 /*We must zero all InternalThread pointers to avoid making the GC unhappy.*/
3127                 memset (wait->threads, 0, MAXIMUM_WAIT_OBJECTS * SIZEOF_VOID_P);
3128                 mono_threads_lock ();
3129                 mono_g_hash_table_foreach (threads, collect_threads_for_suspend, wait);
3130                 mono_threads_unlock ();
3131
3132                 events = g_new0 (gpointer, wait->num);
3133                 eventidx = 0;
3134                 /* Get the suspended events that we'll be waiting for */
3135                 for (i = 0; i < wait->num; ++i) {
3136                         MonoInternalThread *thread = wait->threads [i];
3137                         gboolean signal_suspend = FALSE;
3138
3139                         if ((thread->tid == self) || mono_gc_is_finalizer_internal_thread (thread) || (thread->flags & MONO_THREAD_FLAG_DONT_MANAGE)) {
3140                                 //CloseHandle (wait->handles [i]);
3141                                 wait->threads [i] = NULL; /* ignore this thread in next loop */
3142                                 continue;
3143                         }
3144
3145                         ensure_synch_cs_set (thread);
3146                 
3147                         EnterCriticalSection (thread->synch_cs);
3148
3149                         if (thread->suspended_event == NULL) {
3150                                 thread->suspended_event = CreateEvent (NULL, TRUE, FALSE, NULL);
3151                                 if (thread->suspended_event == NULL) {
3152                                         /* Forget this one and go on to the next */
3153                                         LeaveCriticalSection (thread->synch_cs);
3154                                         continue;
3155                                 }
3156                         }
3157
3158                         if ((thread->state & ThreadState_Suspended) != 0 || 
3159                                 (thread->state & ThreadState_StopRequested) != 0 ||
3160                                 (thread->state & ThreadState_Stopped) != 0) {
3161                                 LeaveCriticalSection (thread->synch_cs);
3162                                 CloseHandle (wait->handles [i]);
3163                                 wait->threads [i] = NULL; /* ignore this thread in next loop */
3164                                 continue;
3165                         }
3166
3167                         if ((thread->state & ThreadState_SuspendRequested) == 0)
3168                                 signal_suspend = TRUE;
3169
3170                         events [eventidx++] = thread->suspended_event;
3171
3172                         /* Convert abort requests into suspend requests */
3173                         if ((thread->state & ThreadState_AbortRequested) != 0)
3174                                 thread->state &= ~ThreadState_AbortRequested;
3175                         
3176                         thread->state |= ThreadState_SuspendRequested;
3177
3178                         LeaveCriticalSection (thread->synch_cs);
3179
3180                         /* Signal the thread to suspend */
3181                         if (mono_thread_info_new_interrupt_enabled ())
3182                                 suspend_thread_internal (thread, TRUE);
3183                         else if (signal_suspend)
3184                                 signal_thread_state_change (thread);
3185                 }
3186
3187                 /*Only wait on the suspend event if we are using the old path */
3188                 if (eventidx > 0 && !mono_thread_info_new_interrupt_enabled ()) {
3189                         WaitForMultipleObjectsEx (eventidx, events, TRUE, 100, FALSE);
3190                         for (i = 0; i < wait->num; ++i) {
3191                                 MonoInternalThread *thread = wait->threads [i];
3192
3193                                 if (thread == NULL)
3194                                         continue;
3195
3196                                 ensure_synch_cs_set (thread);
3197                         
3198                                 EnterCriticalSection (thread->synch_cs);
3199                                 if ((thread->state & ThreadState_Suspended) != 0) {
3200                                         CloseHandle (thread->suspended_event);
3201                                         thread->suspended_event = NULL;
3202                                 }
3203                                 LeaveCriticalSection (thread->synch_cs);
3204                         }
3205                 }
3206                 
3207                 if (eventidx <= 0) {
3208                         /* 
3209                          * If there are threads which are starting up, we wait until they
3210                          * are suspended when they try to register in the threads hash.
3211                          * This is guaranteed to finish, since the threads which can create new
3212                          * threads get suspended after a while.
3213                          * FIXME: The finalizer thread can still create new threads.
3214                          */
3215                         mono_threads_lock ();
3216                         if (threads_starting_up)
3217                                 starting = mono_g_hash_table_size (threads_starting_up) > 0;
3218                         else
3219                                 starting = FALSE;
3220                         mono_threads_unlock ();
3221                         if (starting)
3222                                 Sleep (100);
3223                         else
3224                                 finished = TRUE;
3225                 }
3226
3227                 g_free (events);
3228         }
3229 }
3230
3231 static void
3232 collect_threads (gpointer key, gpointer value, gpointer user_data)
3233 {
3234         MonoInternalThread *thread = (MonoInternalThread*)value;
3235         struct wait_data *wait = (struct wait_data*)user_data;
3236         HANDLE handle;
3237
3238         if (wait->num<MAXIMUM_WAIT_OBJECTS) {
3239                 handle = OpenThread (THREAD_ALL_ACCESS, TRUE, thread->tid);
3240                 if (handle == NULL)
3241                         return;
3242
3243                 wait->handles [wait->num] = handle;
3244                 wait->threads [wait->num] = thread;
3245                 wait->num++;
3246         }
3247 }
3248
3249 static gboolean thread_dump_requested;
3250
3251 static G_GNUC_UNUSED gboolean
3252 print_stack_frame_to_string (MonoStackFrameInfo *frame, MonoContext *ctx, gpointer data)
3253 {
3254         GString *p = (GString*)data;
3255         MonoMethod *method = NULL;
3256         if (frame->ji)
3257                 method = mono_jit_info_get_method (frame->ji);
3258
3259         if (method) {
3260                 gchar *location = mono_debug_print_stack_frame (method, frame->native_offset, frame->domain);
3261                 g_string_append_printf (p, "  %s\n", location);
3262                 g_free (location);
3263         } else
3264                 g_string_append_printf (p, "  at <unknown> <0x%05x>\n", frame->native_offset);
3265
3266         return FALSE;
3267 }
3268
3269 static void
3270 print_thread_dump (MonoInternalThread *thread, MonoThreadInfo *info)
3271 {
3272         GString* text = g_string_new (0);
3273         char *name;
3274         GError *error = NULL;
3275
3276         if (thread->name) {
3277                 name = g_utf16_to_utf8 (thread->name, thread->name_len, NULL, NULL, &error);
3278                 g_assert (!error);
3279                 g_string_append_printf (text, "\n\"%s\"", name);
3280                 g_free (name);
3281         }
3282         else if (thread->threadpool_thread)
3283                 g_string_append (text, "\n\"<threadpool thread>\"");
3284         else
3285                 g_string_append (text, "\n\"<unnamed thread>\"");
3286
3287 #if 0
3288 /* This no longer works with remote unwinding */
3289 #ifndef HOST_WIN32
3290         wapi_desc = wapi_current_thread_desc ();
3291         g_string_append_printf (text, " tid=0x%p this=0x%p %s\n", (gpointer)(gsize)thread->tid, thread,  wapi_desc);
3292         free (wapi_desc);
3293 #endif
3294 #endif
3295
3296         mono_get_eh_callbacks ()->mono_walk_stack_with_state (print_stack_frame_to_string, &info->suspend_state, MONO_UNWIND_SIGNAL_SAFE, text);
3297         mono_thread_info_resume (mono_thread_info_get_tid (info));
3298
3299         fprintf (stdout, "%s", text->str);
3300
3301 #if PLATFORM_WIN32 && TARGET_WIN32 && _DEBUG
3302         OutputDebugStringA(text->str);
3303 #endif
3304
3305         g_string_free (text, TRUE);
3306         fflush (stdout);
3307 }
3308
3309 static void
3310 dump_thread (gpointer key, gpointer value, gpointer user)
3311 {
3312         MonoInternalThread *thread = (MonoInternalThread *)value;
3313         MonoThreadInfo *info;
3314
3315         if (thread == mono_thread_internal_current ())
3316                 return;
3317
3318         /*
3319         FIXME This still can hang if we stop a thread during malloc.
3320         FIXME This can hang if we suspend on a critical method and the GC kicks in. A fix might be to have function
3321         that takes a callback and runs it with the target suspended.
3322         We probably should loop a bit around trying to get it to either managed code
3323         or WSJ state.
3324         */
3325         info = mono_thread_info_safe_suspend_sync ((MonoNativeThreadId)(gpointer)(gsize)thread->tid, FALSE);
3326
3327         if (!info)
3328                 return;
3329
3330         print_thread_dump (thread, info);
3331 }
3332
3333 void
3334 mono_threads_perform_thread_dump (void)
3335 {
3336         if (!thread_dump_requested)
3337                 return;
3338
3339         printf ("Full thread dump:\n");
3340
3341         /* 
3342          * Make a copy of the hashtable since we can't do anything with
3343          * threads while threads_mutex is held.
3344          */
3345         mono_threads_lock ();
3346         mono_g_hash_table_foreach (threads, dump_thread, NULL);
3347         mono_threads_unlock ();
3348
3349         thread_dump_requested = FALSE;
3350 }
3351
3352 /**
3353  * mono_threads_request_thread_dump:
3354  *
3355  *   Ask all threads except the current to print their stacktrace to stdout.
3356  */
3357 void
3358 mono_threads_request_thread_dump (void)
3359 {
3360         struct wait_data wait_data;
3361         struct wait_data *wait = &wait_data;
3362         int i;
3363
3364         /*The new thread dump code runs out of the finalizer thread. */
3365         if (mono_thread_info_new_interrupt_enabled ()) {
3366                 thread_dump_requested = TRUE;
3367                 mono_gc_finalize_notify ();
3368                 return;
3369         }
3370
3371
3372         memset (wait, 0, sizeof (struct wait_data));
3373
3374         /* 
3375          * Make a copy of the hashtable since we can't do anything with
3376          * threads while threads_mutex is held.
3377          */
3378         mono_threads_lock ();
3379         mono_g_hash_table_foreach (threads, collect_threads, wait);
3380         mono_threads_unlock ();
3381
3382         for (i = 0; i < wait->num; ++i) {
3383                 MonoInternalThread *thread = wait->threads [i];
3384
3385                 if (!mono_gc_is_finalizer_internal_thread (thread) &&
3386                                 (thread != mono_thread_internal_current ()) &&
3387                                 !thread->thread_dump_requested) {
3388                         thread->thread_dump_requested = TRUE;
3389
3390                         signal_thread_state_change (thread);
3391                 }
3392
3393                 CloseHandle (wait->handles [i]);
3394         }
3395 }
3396
3397 struct ref_stack {
3398         gpointer *refs;
3399         gint allocated; /* +1 so that refs [allocated] == NULL */
3400         gint bottom;
3401 };
3402
3403 typedef struct ref_stack RefStack;
3404
3405 static RefStack *
3406 ref_stack_new (gint initial_size)
3407 {
3408         RefStack *rs;
3409
3410         initial_size = MAX (initial_size, 16) + 1;
3411         rs = g_new0 (RefStack, 1);
3412         rs->refs = g_new0 (gpointer, initial_size);
3413         rs->allocated = initial_size;
3414         return rs;
3415 }
3416
3417 static void
3418 ref_stack_destroy (gpointer ptr)
3419 {
3420         RefStack *rs = ptr;
3421
3422         if (rs != NULL) {
3423                 g_free (rs->refs);
3424                 g_free (rs);
3425         }
3426 }
3427
3428 static void
3429 ref_stack_push (RefStack *rs, gpointer ptr)
3430 {
3431         g_assert (rs != NULL);
3432
3433         if (rs->bottom >= rs->allocated) {
3434                 rs->refs = g_realloc (rs->refs, rs->allocated * 2 * sizeof (gpointer) + 1);
3435                 rs->allocated <<= 1;
3436                 rs->refs [rs->allocated] = NULL;
3437         }
3438         rs->refs [rs->bottom++] = ptr;
3439 }
3440
3441 static void
3442 ref_stack_pop (RefStack *rs)
3443 {
3444         if (rs == NULL || rs->bottom == 0)
3445                 return;
3446
3447         rs->bottom--;
3448         rs->refs [rs->bottom] = NULL;
3449 }
3450
3451 static gboolean
3452 ref_stack_find (RefStack *rs, gpointer ptr)
3453 {
3454         gpointer *refs;
3455
3456         if (rs == NULL)
3457                 return FALSE;
3458
3459         for (refs = rs->refs; refs && *refs; refs++) {
3460                 if (*refs == ptr)
3461                         return TRUE;
3462         }
3463         return FALSE;
3464 }
3465
3466 /*
3467  * mono_thread_push_appdomain_ref:
3468  *
3469  *   Register that the current thread may have references to objects in domain 
3470  * @domain on its stack. Each call to this function should be paired with a 
3471  * call to pop_appdomain_ref.
3472  */
3473 void 
3474 mono_thread_push_appdomain_ref (MonoDomain *domain)
3475 {
3476         MonoInternalThread *thread = mono_thread_internal_current ();
3477
3478         if (thread) {
3479                 /* printf ("PUSH REF: %"G_GSIZE_FORMAT" -> %s.\n", (gsize)thread->tid, domain->friendly_name); */
3480                 SPIN_LOCK (thread->lock_thread_id);
3481                 if (thread->appdomain_refs == NULL)
3482                         thread->appdomain_refs = ref_stack_new (16);
3483                 ref_stack_push (thread->appdomain_refs, domain);
3484                 SPIN_UNLOCK (thread->lock_thread_id);
3485         }
3486 }
3487
3488 void
3489 mono_thread_pop_appdomain_ref (void)
3490 {
3491         MonoInternalThread *thread = mono_thread_internal_current ();
3492
3493         if (thread) {
3494                 /* printf ("POP REF: %"G_GSIZE_FORMAT" -> %s.\n", (gsize)thread->tid, ((MonoDomain*)(thread->appdomain_refs->data))->friendly_name); */
3495                 SPIN_LOCK (thread->lock_thread_id);
3496                 ref_stack_pop (thread->appdomain_refs);
3497                 SPIN_UNLOCK (thread->lock_thread_id);
3498         }
3499 }
3500
3501 gboolean
3502 mono_thread_internal_has_appdomain_ref (MonoInternalThread *thread, MonoDomain *domain)
3503 {
3504         gboolean res;
3505         SPIN_LOCK (thread->lock_thread_id);
3506         res = ref_stack_find (thread->appdomain_refs, domain);
3507         SPIN_UNLOCK (thread->lock_thread_id);
3508         return res;
3509 }
3510
3511 gboolean
3512 mono_thread_has_appdomain_ref (MonoThread *thread, MonoDomain *domain)
3513 {
3514         return mono_thread_internal_has_appdomain_ref (thread->internal_thread, domain);
3515 }
3516
3517 typedef struct abort_appdomain_data {
3518         struct wait_data wait;
3519         MonoDomain *domain;
3520 } abort_appdomain_data;
3521
3522 static void
3523 collect_appdomain_thread (gpointer key, gpointer value, gpointer user_data)
3524 {
3525         MonoInternalThread *thread = (MonoInternalThread*)value;
3526         abort_appdomain_data *data = (abort_appdomain_data*)user_data;
3527         MonoDomain *domain = data->domain;
3528
3529         if (mono_thread_internal_has_appdomain_ref (thread, domain)) {
3530                 /* printf ("ABORTING THREAD %p BECAUSE IT REFERENCES DOMAIN %s.\n", thread->tid, domain->friendly_name); */
3531
3532                 if(data->wait.num<MAXIMUM_WAIT_OBJECTS) {
3533                         HANDLE handle = OpenThread (THREAD_ALL_ACCESS, TRUE, thread->tid);
3534                         if (handle == NULL)
3535                                 return;
3536                         data->wait.handles [data->wait.num] = handle;
3537                         data->wait.threads [data->wait.num] = thread;
3538                         data->wait.num++;
3539                 } else {
3540                         /* Just ignore the rest, we can't do anything with
3541                          * them yet
3542                          */
3543                 }
3544         }
3545 }
3546
3547 /*
3548  * mono_threads_abort_appdomain_threads:
3549  *
3550  *   Abort threads which has references to the given appdomain.
3551  */
3552 gboolean
3553 mono_threads_abort_appdomain_threads (MonoDomain *domain, int timeout)
3554 {
3555 #ifdef __native_client__
3556         return FALSE;
3557 #endif
3558
3559         abort_appdomain_data user_data;
3560         guint32 start_time;
3561         int orig_timeout = timeout;
3562         int i;
3563
3564         THREAD_DEBUG (g_message ("%s: starting abort", __func__));
3565
3566         start_time = mono_msec_ticks ();
3567         do {
3568                 mono_threads_lock ();
3569
3570                 user_data.domain = domain;
3571                 user_data.wait.num = 0;
3572                 /* This shouldn't take any locks */
3573                 mono_g_hash_table_foreach (threads, collect_appdomain_thread, &user_data);
3574                 mono_threads_unlock ();
3575
3576                 if (user_data.wait.num > 0) {
3577                         /* Abort the threads outside the threads lock */
3578                         for (i = 0; i < user_data.wait.num; ++i)
3579                                 ves_icall_System_Threading_Thread_Abort (user_data.wait.threads [i], NULL);
3580
3581                         /*
3582                          * We should wait for the threads either to abort, or to leave the
3583                          * domain. We can't do the latter, so we wait with a timeout.
3584                          */
3585                         wait_for_tids (&user_data.wait, 100);
3586                 }
3587
3588                 /* Update remaining time */
3589                 timeout -= mono_msec_ticks () - start_time;
3590                 start_time = mono_msec_ticks ();
3591
3592                 if (orig_timeout != -1 && timeout < 0)
3593                         return FALSE;
3594         }
3595         while (user_data.wait.num > 0);
3596
3597         THREAD_DEBUG (g_message ("%s: abort done", __func__));
3598
3599         return TRUE;
3600 }
3601
3602 static void
3603 clear_cached_culture (gpointer key, gpointer value, gpointer user_data)
3604 {
3605         MonoInternalThread *thread = (MonoInternalThread*)value;
3606         MonoDomain *domain = (MonoDomain*)user_data;
3607         int i;
3608
3609         /* No locking needed here */
3610         /* FIXME: why no locking? writes to the cache are protected with synch_cs above */
3611
3612         if (thread->cached_culture_info) {
3613                 for (i = 0; i < NUM_CACHED_CULTURES * 2; ++i) {
3614                         MonoObject *obj = mono_array_get (thread->cached_culture_info, MonoObject*, i);
3615                         if (obj && obj->vtable->domain == domain)
3616                                 mono_array_set (thread->cached_culture_info, MonoObject*, i, NULL);
3617                 }
3618         }
3619 }
3620         
3621 /*
3622  * mono_threads_clear_cached_culture:
3623  *
3624  *   Clear the cached_current_culture from all threads if it is in the
3625  * given appdomain.
3626  */
3627 void
3628 mono_threads_clear_cached_culture (MonoDomain *domain)
3629 {
3630         mono_threads_lock ();
3631         mono_g_hash_table_foreach (threads, clear_cached_culture, domain);
3632         mono_threads_unlock ();
3633 }
3634
3635 /*
3636  * mono_thread_get_undeniable_exception:
3637  *
3638  *   Return an exception which needs to be raised when leaving a catch clause.
3639  * This is used for undeniable exception propagation.
3640  */
3641 MonoException*
3642 mono_thread_get_undeniable_exception (void)
3643 {
3644         MonoInternalThread *thread = mono_thread_internal_current ();
3645
3646         if (thread && thread->abort_exc && !is_running_protected_wrapper ()) {
3647                 /*
3648                  * FIXME: Clear the abort exception and return an AppDomainUnloaded 
3649                  * exception if the thread no longer references a dying appdomain.
3650                  */
3651                 thread->abort_exc->trace_ips = NULL;
3652                 thread->abort_exc->stack_trace = NULL;
3653                 return thread->abort_exc;
3654         }
3655
3656         return NULL;
3657 }
3658
3659 #if MONO_SMALL_CONFIG
3660 #define NUM_STATIC_DATA_IDX 4
3661 static const int static_data_size [NUM_STATIC_DATA_IDX] = {
3662         64, 256, 1024, 4096
3663 };
3664 #else
3665 #define NUM_STATIC_DATA_IDX 8
3666 static const int static_data_size [NUM_STATIC_DATA_IDX] = {
3667         1024, 4096, 16384, 65536, 262144, 1048576, 4194304, 16777216
3668 };
3669 #endif
3670
3671 static uintptr_t* static_reference_bitmaps [NUM_STATIC_DATA_IDX];
3672
3673 static void
3674 mark_tls_slots (void *addr, MonoGCMarkFunc mark_func)
3675 {
3676         int i;
3677         gpointer *static_data = addr;
3678         for (i = 0; i < NUM_STATIC_DATA_IDX; ++i) {
3679                 int j, numwords;
3680                 void **ptr;
3681                 if (!static_data [i])
3682                         continue;
3683                 numwords = 1 + static_data_size [i] / sizeof (gpointer) / (sizeof(uintptr_t) * 8);
3684                 ptr = static_data [i];
3685                 for (j = 0; j < numwords; ++j, ptr += sizeof (uintptr_t) * 8) {
3686                         uintptr_t bmap = static_reference_bitmaps [i][j];
3687                         void ** p = ptr;
3688                         while (bmap) {
3689                                 if ((bmap & 1) && *p) {
3690                                         mark_func (p);
3691                                 }
3692                                 p++;
3693                                 bmap >>= 1;
3694                         }
3695                 }
3696         }
3697 }
3698
3699 /*
3700  *  mono_alloc_static_data
3701  *
3702  *   Allocate memory blocks for storing threads or context static data
3703  */
3704 static void 
3705 mono_alloc_static_data (gpointer **static_data_ptr, guint32 offset, gboolean threadlocal)
3706 {
3707         guint idx = (offset >> 24) - 1;
3708         int i;
3709
3710         gpointer* static_data = *static_data_ptr;
3711         if (!static_data) {
3712                 static void* tls_desc = NULL;
3713                 if (mono_gc_user_markers_supported () && !tls_desc)
3714                         tls_desc = mono_gc_make_root_descr_user (mark_tls_slots);
3715                 static_data = mono_gc_alloc_fixed (static_data_size [0], threadlocal?tls_desc:NULL);
3716                 *static_data_ptr = static_data;
3717                 static_data [0] = static_data;
3718         }
3719
3720         for (i = 1; i <= idx; ++i) {
3721                 if (static_data [i])
3722                         continue;
3723                 if (mono_gc_user_markers_supported () && threadlocal)
3724                         static_data [i] = g_malloc0 (static_data_size [i]);
3725                 else
3726                         static_data [i] = mono_gc_alloc_fixed (static_data_size [i], NULL);
3727         }
3728 }
3729
3730 static void 
3731 mono_free_static_data (gpointer* static_data, gboolean threadlocal)
3732 {
3733         int i;
3734         for (i = 1; i < NUM_STATIC_DATA_IDX; ++i) {
3735                 gpointer p = static_data [i];
3736                 if (!p)
3737                         continue;
3738                 /*
3739                  * At this point, the static data pointer array is still registered with the
3740                  * GC, so must ensure that mark_tls_slots() will not encounter any invalid
3741                  * data.  Freeing the individual arrays without first nulling their slots
3742                  * would make it possible for mark_tls_slots() to encounter a pointer to
3743                  * such an already freed array.  See bug #13813.
3744                  */
3745                 static_data [i] = NULL;
3746                 mono_memory_write_barrier ();
3747                 if (mono_gc_user_markers_supported () && threadlocal)
3748                         g_free (p);
3749                 else
3750                         mono_gc_free_fixed (p);
3751         }
3752         mono_gc_free_fixed (static_data);
3753 }
3754
3755 /*
3756  *  mono_init_static_data_info
3757  *
3758  *   Initializes static data counters
3759  */
3760 static void mono_init_static_data_info (StaticDataInfo *static_data)
3761 {
3762         static_data->idx = 0;
3763         static_data->offset = 0;
3764         static_data->freelist = NULL;
3765 }
3766
3767 /*
3768  *  mono_alloc_static_data_slot
3769  *
3770  *   Generates an offset for static data. static_data contains the counters
3771  *  used to generate it.
3772  */
3773 static guint32
3774 mono_alloc_static_data_slot (StaticDataInfo *static_data, guint32 size, guint32 align)
3775 {
3776         guint32 offset;
3777
3778         if (!static_data->idx && !static_data->offset) {
3779                 /* 
3780                  * we use the first chunk of the first allocation also as
3781                  * an array for the rest of the data 
3782                  */
3783                 static_data->offset = sizeof (gpointer) * NUM_STATIC_DATA_IDX;
3784         }
3785         static_data->offset += align - 1;
3786         static_data->offset &= ~(align - 1);
3787         if (static_data->offset + size >= static_data_size [static_data->idx]) {
3788                 static_data->idx ++;
3789                 g_assert (size <= static_data_size [static_data->idx]);
3790                 g_assert (static_data->idx < NUM_STATIC_DATA_IDX);
3791                 static_data->offset = 0;
3792         }
3793         offset = static_data->offset | ((static_data->idx + 1) << 24);
3794         static_data->offset += size;
3795         return offset;
3796 }
3797
3798 /* 
3799  * ensure thread static fields already allocated are valid for thread
3800  * This function is called when a thread is created or on thread attach.
3801  */
3802 static void
3803 thread_adjust_static_data (MonoInternalThread *thread)
3804 {
3805         guint32 offset;
3806
3807         mono_threads_lock ();
3808         if (thread_static_info.offset || thread_static_info.idx > 0) {
3809                 /* get the current allocated size */
3810                 offset = thread_static_info.offset | ((thread_static_info.idx + 1) << 24);
3811                 mono_alloc_static_data (&(thread->static_data), offset, TRUE);
3812         }
3813         mono_threads_unlock ();
3814 }
3815
3816 static void 
3817 alloc_thread_static_data_helper (gpointer key, gpointer value, gpointer user)
3818 {
3819         MonoInternalThread *thread = value;
3820         guint32 offset = GPOINTER_TO_UINT (user);
3821
3822         mono_alloc_static_data (&(thread->static_data), offset, TRUE);
3823 }
3824
3825 static MonoThreadDomainTls*
3826 search_tls_slot_in_freelist (StaticDataInfo *static_data, guint32 size, guint32 align)
3827 {
3828         MonoThreadDomainTls* prev = NULL;
3829         MonoThreadDomainTls* tmp = static_data->freelist;
3830         while (tmp) {
3831                 if (tmp->size == size) {
3832                         if (prev)
3833                                 prev->next = tmp->next;
3834                         else
3835                                 static_data->freelist = tmp->next;
3836                         return tmp;
3837                 }
3838                 tmp = tmp->next;
3839         }
3840         return NULL;
3841 }
3842
3843 static void
3844 update_tls_reference_bitmap (guint32 offset, uintptr_t *bitmap, int numbits)
3845 {
3846         int i;
3847         int idx = (offset >> 24) - 1;
3848         uintptr_t *rb;
3849         if (!static_reference_bitmaps [idx])
3850                 static_reference_bitmaps [idx] = g_new0 (uintptr_t, 1 + static_data_size [idx] / sizeof(gpointer) / (sizeof(uintptr_t) * 8));
3851         rb = static_reference_bitmaps [idx];
3852         offset &= 0xffffff;
3853         offset /= sizeof (gpointer);
3854         /* offset is now the bitmap offset */
3855         for (i = 0; i < numbits; ++i) {
3856                 if (bitmap [i / sizeof (uintptr_t)] & (1L << (i & (sizeof (uintptr_t) * 8 -1))))
3857                         rb [(offset + i) / (sizeof (uintptr_t) * 8)] |= (1L << ((offset + i) & (sizeof (uintptr_t) * 8 -1)));
3858         }
3859 }
3860
3861 static void
3862 clear_reference_bitmap (guint32 offset, guint32 size)
3863 {
3864         int idx = (offset >> 24) - 1;
3865         uintptr_t *rb;
3866         rb = static_reference_bitmaps [idx];
3867         offset &= 0xffffff;
3868         offset /= sizeof (gpointer);
3869         size /= sizeof (gpointer);
3870         size += offset;
3871         /* offset is now the bitmap offset */
3872         for (; offset < size; ++offset)
3873                 rb [offset / (sizeof (uintptr_t) * 8)] &= ~(1L << (offset & (sizeof (uintptr_t) * 8 -1)));
3874 }
3875
3876 /*
3877  * The offset for a special static variable is composed of three parts:
3878  * a bit that indicates the type of static data (0:thread, 1:context),
3879  * an index in the array of chunks of memory for the thread (thread->static_data)
3880  * and an offset in that chunk of mem. This allows allocating less memory in the 
3881  * common case.
3882  */
3883
3884 guint32
3885 mono_alloc_special_static_data (guint32 static_type, guint32 size, guint32 align, uintptr_t *bitmap, int numbits)
3886 {
3887         guint32 offset;
3888         if (static_type == SPECIAL_STATIC_THREAD) {
3889                 MonoThreadDomainTls *item;
3890                 mono_threads_lock ();
3891                 item = search_tls_slot_in_freelist (&thread_static_info, size, align);
3892                 /*g_print ("TLS alloc: %d in domain %p (total: %d), cached: %p\n", size, mono_domain_get (), thread_static_info.offset, item);*/
3893                 if (item) {
3894                         offset = item->offset;
3895                         g_free (item);
3896                 } else {
3897                         offset = mono_alloc_static_data_slot (&thread_static_info, size, align);
3898                 }
3899                 update_tls_reference_bitmap (offset, bitmap, numbits);
3900                 /* This can be called during startup */
3901                 if (threads != NULL)
3902                         mono_g_hash_table_foreach (threads, alloc_thread_static_data_helper, GUINT_TO_POINTER (offset));
3903                 mono_threads_unlock ();
3904         } else {
3905                 g_assert (static_type == SPECIAL_STATIC_CONTEXT);
3906                 mono_contexts_lock ();
3907                 offset = mono_alloc_static_data_slot (&context_static_info, size, align);
3908                 mono_contexts_unlock ();
3909                 offset |= 0x80000000;   /* Set the high bit to indicate context static data */
3910         }
3911         return offset;
3912 }
3913
3914 gpointer
3915 mono_get_special_static_data_for_thread (MonoInternalThread *thread, guint32 offset)
3916 {
3917         /* The high bit means either thread (0) or static (1) data. */
3918
3919         guint32 static_type = (offset & 0x80000000);
3920         int idx;
3921
3922         offset &= 0x7fffffff;
3923         idx = (offset >> 24) - 1;
3924
3925         if (static_type == 0) {
3926                 return get_thread_static_data (thread, offset);
3927         } else {
3928                 /* Allocate static data block under demand, since we don't have a list
3929                 // of contexts
3930                 */
3931                 MonoAppContext *context = mono_context_get ();
3932                 if (!context->static_data || !context->static_data [idx]) {
3933                         mono_contexts_lock ();
3934                         mono_alloc_static_data (&(context->static_data), offset, FALSE);
3935                         mono_contexts_unlock ();
3936                 }
3937                 return ((char*) context->static_data [idx]) + (offset & 0xffffff);      
3938         }
3939 }
3940
3941 gpointer
3942 mono_get_special_static_data (guint32 offset)
3943 {
3944         return mono_get_special_static_data_for_thread (mono_thread_internal_current (), offset);
3945 }
3946
3947 typedef struct {
3948         guint32 offset;
3949         guint32 size;
3950 } TlsOffsetSize;
3951
3952 static void 
3953 free_thread_static_data_helper (gpointer key, gpointer value, gpointer user)
3954 {
3955         MonoInternalThread *thread = value;
3956         TlsOffsetSize *data = user;
3957         int idx = (data->offset >> 24) - 1;
3958         char *ptr;
3959
3960         if (!thread->static_data || !thread->static_data [idx])
3961                 return;
3962         ptr = ((char*) thread->static_data [idx]) + (data->offset & 0xffffff);
3963         mono_gc_bzero (ptr, data->size);
3964 }
3965
3966 static void
3967 do_free_special_slot (guint32 offset, guint32 size)
3968 {
3969         guint32 static_type = (offset & 0x80000000);
3970         /*g_print ("free %s , size: %d, offset: %x\n", field->name, size, offset);*/
3971         if (static_type == 0) {
3972                 TlsOffsetSize data;
3973                 MonoThreadDomainTls *item = g_new0 (MonoThreadDomainTls, 1);
3974                 data.offset = offset & 0x7fffffff;
3975                 data.size = size;
3976                 clear_reference_bitmap (data.offset, data.size);
3977                 if (threads != NULL)
3978                         mono_g_hash_table_foreach (threads, free_thread_static_data_helper, &data);
3979                 item->offset = offset;
3980                 item->size = size;
3981
3982                 if (!mono_runtime_is_shutting_down ()) {
3983                         item->next = thread_static_info.freelist;
3984                         thread_static_info.freelist = item;
3985                 } else {
3986                         /* We could be called during shutdown after mono_thread_cleanup () is called */
3987                         g_free (item);
3988                 }
3989         } else {
3990                 /* FIXME: free context static data as well */
3991         }
3992 }
3993
3994 static void
3995 do_free_special (gpointer key, gpointer value, gpointer data)
3996 {
3997         MonoClassField *field = key;
3998         guint32 offset = GPOINTER_TO_UINT (value);
3999         gint32 align;
4000         guint32 size;
4001         size = mono_type_size (field->type, &align);
4002         do_free_special_slot (offset, size);
4003 }
4004
4005 void
4006 mono_alloc_special_static_data_free (GHashTable *special_static_fields)
4007 {
4008         mono_threads_lock ();
4009         g_hash_table_foreach (special_static_fields, do_free_special, NULL);
4010         mono_threads_unlock ();
4011 }
4012
4013 void
4014 mono_special_static_data_free_slot (guint32 offset, guint32 size)
4015 {
4016         mono_threads_lock ();
4017         do_free_special_slot (offset, size);
4018         mono_threads_unlock ();
4019 }
4020
4021 /*
4022  * allocates room in the thread local area for storing an instance of the struct type
4023  * the allocation is kept track of in domain->tlsrec_list.
4024  */
4025 uint32_t
4026 mono_thread_alloc_tls (MonoReflectionType *type)
4027 {
4028         MonoDomain *domain = mono_domain_get ();
4029         MonoClass *klass;
4030         MonoTlsDataRecord *tlsrec;
4031         int max_set = 0;
4032         gsize *bitmap;
4033         gsize default_bitmap [4] = {0};
4034         uint32_t tls_offset;
4035         guint32 size;
4036         gint32 align;
4037
4038         klass = mono_class_from_mono_type (type->type);
4039         /* TlsDatum is a struct, so we subtract the object header size offset */
4040         bitmap = mono_class_compute_bitmap (klass, default_bitmap, sizeof (default_bitmap) * 8, - (int)(sizeof (MonoObject) / sizeof (gpointer)), &max_set, FALSE);
4041         size = mono_type_size (type->type, &align);
4042         tls_offset = mono_alloc_special_static_data (SPECIAL_STATIC_THREAD, size, align, (uintptr_t*)bitmap, max_set + 1);
4043         if (bitmap != default_bitmap)
4044                 g_free (bitmap);
4045         tlsrec = g_new0 (MonoTlsDataRecord, 1);
4046         tlsrec->tls_offset = tls_offset;
4047         tlsrec->size = size;
4048         mono_domain_lock (domain);
4049         tlsrec->next = domain->tlsrec_list;
4050         domain->tlsrec_list = tlsrec;
4051         mono_domain_unlock (domain);
4052         return tls_offset;
4053 }
4054
4055 void
4056 mono_thread_destroy_tls (uint32_t tls_offset)
4057 {
4058         MonoTlsDataRecord *prev = NULL;
4059         MonoTlsDataRecord *cur;
4060         guint32 size = 0;
4061         MonoDomain *domain = mono_domain_get ();
4062         mono_domain_lock (domain);
4063         cur = domain->tlsrec_list;
4064         while (cur) {
4065                 if (cur->tls_offset == tls_offset) {
4066                         if (prev)
4067                                 prev->next = cur->next;
4068                         else
4069                                 domain->tlsrec_list = cur->next;
4070                         size = cur->size;
4071                         g_free (cur);
4072                         break;
4073                 }
4074                 prev = cur;
4075                 cur = cur->next;
4076         }
4077         mono_domain_unlock (domain);
4078         if (size)
4079                 mono_special_static_data_free_slot (tls_offset, size);
4080 }
4081
4082 /*
4083  * This is just to ensure cleanup: the finalizers should have taken care, so this is not perf-critical.
4084  */
4085 void
4086 mono_thread_destroy_domain_tls (MonoDomain *domain)
4087 {
4088         while (domain->tlsrec_list)
4089                 mono_thread_destroy_tls (domain->tlsrec_list->tls_offset);
4090 }
4091
4092 static MonoClassField *local_slots = NULL;
4093
4094 typedef struct {
4095         /* local tls data to get locals_slot from a thread */
4096         guint32 offset;
4097         int idx;
4098         /* index in the locals_slot array */
4099         int slot;
4100 } LocalSlotID;
4101
4102 static void
4103 clear_local_slot (gpointer key, gpointer value, gpointer user_data)
4104 {
4105         LocalSlotID *sid = user_data;
4106         MonoInternalThread *thread = (MonoInternalThread*)value;
4107         MonoArray *slots_array;
4108         /*
4109          * the static field is stored at: ((char*) thread->static_data [idx]) + (offset & 0xffffff);
4110          * it is for the right domain, so we need to check if it is allocated an initialized
4111          * for the current thread.
4112          */
4113         /*g_print ("handling thread %p\n", thread);*/
4114         if (!thread->static_data || !thread->static_data [sid->idx])
4115                 return;
4116         slots_array = *(MonoArray **)(((char*) thread->static_data [sid->idx]) + (sid->offset & 0xffffff));
4117         if (!slots_array || sid->slot >= mono_array_length (slots_array))
4118                 return;
4119         mono_array_set (slots_array, MonoObject*, sid->slot, NULL);
4120 }
4121
4122 void
4123 mono_thread_free_local_slot_values (int slot, MonoBoolean thread_local)
4124 {
4125         MonoDomain *domain;
4126         LocalSlotID sid;
4127         sid.slot = slot;
4128         if (thread_local) {
4129                 void *addr = NULL;
4130                 if (!local_slots) {
4131                         local_slots = mono_class_get_field_from_name (mono_defaults.thread_class, "local_slots");
4132                         if (!local_slots) {
4133                                 g_warning ("local_slots field not found in Thread class");
4134                                 return;
4135                         }
4136                 }
4137                 domain = mono_domain_get ();
4138                 mono_domain_lock (domain);
4139                 if (domain->special_static_fields)
4140                         addr = g_hash_table_lookup (domain->special_static_fields, local_slots);
4141                 mono_domain_unlock (domain);
4142                 if (!addr)
4143                         return;
4144                 /*g_print ("freeing slot %d at %p\n", slot, addr);*/
4145                 sid.offset = GPOINTER_TO_UINT (addr);
4146                 sid.offset &= 0x7fffffff;
4147                 sid.idx = (sid.offset >> 24) - 1;
4148                 mono_threads_lock ();
4149                 mono_g_hash_table_foreach (threads, clear_local_slot, &sid);
4150                 mono_threads_unlock ();
4151         } else {
4152                 /* FIXME: clear the slot for MonoAppContexts, too */
4153         }
4154 }
4155
4156 #ifdef HOST_WIN32
4157 static void CALLBACK dummy_apc (ULONG_PTR param)
4158 {
4159 }
4160 #else
4161 static guint32 dummy_apc (gpointer param)
4162 {
4163         return 0;
4164 }
4165 #endif
4166
4167 /*
4168  * mono_thread_execute_interruption
4169  * 
4170  * Performs the operation that the requested thread state requires (abort,
4171  * suspend or stop)
4172  */
4173 static MonoException* mono_thread_execute_interruption (MonoInternalThread *thread)
4174 {
4175         ensure_synch_cs_set (thread);
4176         
4177         EnterCriticalSection (thread->synch_cs);
4178
4179         /* MonoThread::interruption_requested can only be changed with atomics */
4180         if (InterlockedCompareExchange (&thread->interruption_requested, FALSE, TRUE)) {
4181                 /* this will consume pending APC calls */
4182                 WaitForSingleObjectEx (GetCurrentThread(), 0, TRUE);
4183                 InterlockedDecrement (&thread_interruption_requested);
4184 #ifndef HOST_WIN32
4185                 /* Clear the interrupted flag of the thread so it can wait again */
4186                 wapi_clear_interruption ();
4187 #endif
4188         }
4189
4190         if ((thread->state & ThreadState_AbortRequested) != 0) {
4191                 LeaveCriticalSection (thread->synch_cs);
4192                 if (thread->abort_exc == NULL) {
4193                         /* 
4194                          * This might be racy, but it has to be called outside the lock
4195                          * since it calls managed code.
4196                          */
4197                         MONO_OBJECT_SETREF (thread, abort_exc, mono_get_exception_thread_abort ());
4198                 }
4199                 return thread->abort_exc;
4200         }
4201         else if ((thread->state & ThreadState_SuspendRequested) != 0) {
4202                 self_suspend_internal (thread);         
4203                 return NULL;
4204         }
4205         else if ((thread->state & ThreadState_StopRequested) != 0) {
4206                 /* FIXME: do this through the JIT? */
4207
4208                 LeaveCriticalSection (thread->synch_cs);
4209                 
4210                 mono_thread_exit ();
4211                 return NULL;
4212         } else if (thread->pending_exception) {
4213                 MonoException *exc;
4214
4215                 exc = thread->pending_exception;
4216                 thread->pending_exception = NULL;
4217
4218         LeaveCriticalSection (thread->synch_cs);
4219         return exc;
4220         } else if (thread->thread_interrupt_requested) {
4221
4222                 thread->thread_interrupt_requested = FALSE;
4223                 LeaveCriticalSection (thread->synch_cs);
4224                 
4225                 return(mono_get_exception_thread_interrupted ());
4226         }
4227         
4228         LeaveCriticalSection (thread->synch_cs);
4229         
4230         return NULL;
4231 }
4232
4233 /*
4234  * mono_thread_request_interruption
4235  *
4236  * A signal handler can call this method to request the interruption of a
4237  * thread. The result of the interruption will depend on the current state of
4238  * the thread. If the result is an exception that needs to be throw, it is 
4239  * provided as return value.
4240  */
4241 MonoException*
4242 mono_thread_request_interruption (gboolean running_managed)
4243 {
4244         MonoInternalThread *thread = mono_thread_internal_current ();
4245
4246         /* The thread may already be stopping */
4247         if (thread == NULL) 
4248                 return NULL;
4249
4250 #ifdef HOST_WIN32
4251         if (thread->interrupt_on_stop && 
4252                 thread->state & ThreadState_StopRequested && 
4253                 thread->state & ThreadState_Background)
4254                 ExitThread (1);
4255 #endif
4256         
4257         if (InterlockedCompareExchange (&thread->interruption_requested, 1, 0) == 1)
4258                 return NULL;
4259         InterlockedIncrement (&thread_interruption_requested);
4260
4261         if (!running_managed || is_running_protected_wrapper ()) {
4262                 /* Can't stop while in unmanaged code. Increase the global interruption
4263                    request count. When exiting the unmanaged method the count will be
4264                    checked and the thread will be interrupted. */
4265                 
4266
4267                 if (mono_thread_notify_pending_exc_fn && !running_managed)
4268                         /* The JIT will notify the thread about the interruption */
4269                         /* This shouldn't take any locks */
4270                         mono_thread_notify_pending_exc_fn ();
4271
4272                 /* this will awake the thread if it is in WaitForSingleObject 
4273                    or similar */
4274                 /* Our implementation of this function ignores the func argument */
4275                 QueueUserAPC ((PAPCFUNC)dummy_apc, thread->handle, NULL);
4276                 return NULL;
4277         }
4278         else {
4279                 return mono_thread_execute_interruption (thread);
4280         }
4281 }
4282
4283 /*This function should be called by a thread after it has exited all of
4284  * its handle blocks at interruption time.*/
4285 MonoException*
4286 mono_thread_resume_interruption (void)
4287 {
4288         MonoInternalThread *thread = mono_thread_internal_current ();
4289         gboolean still_aborting;
4290
4291         /* The thread may already be stopping */
4292         if (thread == NULL)
4293                 return NULL;
4294
4295         ensure_synch_cs_set (thread);
4296         EnterCriticalSection (thread->synch_cs);
4297         still_aborting = (thread->state & ThreadState_AbortRequested) != 0;
4298         LeaveCriticalSection (thread->synch_cs);
4299
4300         /*This can happen if the protected block called Thread::ResetAbort*/
4301         if (!still_aborting)
4302                 return FALSE;
4303
4304         if (InterlockedCompareExchange (&thread->interruption_requested, 1, 0) == 1)
4305                 return NULL;
4306         InterlockedIncrement (&thread_interruption_requested);
4307
4308 #ifndef HOST_WIN32
4309         wapi_self_interrupt ();
4310 #endif
4311         return mono_thread_execute_interruption (thread);
4312 }
4313
4314 gboolean mono_thread_interruption_requested ()
4315 {
4316         if (thread_interruption_requested) {
4317                 MonoInternalThread *thread = mono_thread_internal_current ();
4318                 /* The thread may already be stopping */
4319                 if (thread != NULL) 
4320                         return (thread->interruption_requested);
4321         }
4322         return FALSE;
4323 }
4324
4325 static void mono_thread_interruption_checkpoint_request (gboolean bypass_abort_protection)
4326 {
4327         MonoInternalThread *thread = mono_thread_internal_current ();
4328
4329         /* The thread may already be stopping */
4330         if (thread == NULL)
4331                 return;
4332
4333         mono_debugger_check_interruption ();
4334
4335         if (thread->interruption_requested && (bypass_abort_protection || !is_running_protected_wrapper ())) {
4336                 MonoException* exc = mono_thread_execute_interruption (thread);
4337                 if (exc) mono_raise_exception (exc);
4338         }
4339 }
4340
4341 /*
4342  * Performs the interruption of the current thread, if one has been requested,
4343  * and the thread is not running a protected wrapper.
4344  */
4345 void mono_thread_interruption_checkpoint ()
4346 {
4347         mono_thread_interruption_checkpoint_request (FALSE);
4348 }
4349
4350 /*
4351  * Performs the interruption of the current thread, if one has been requested.
4352  */
4353 void mono_thread_force_interruption_checkpoint ()
4354 {
4355         mono_thread_interruption_checkpoint_request (TRUE);
4356 }
4357
4358 /*
4359  * mono_thread_get_and_clear_pending_exception:
4360  *
4361  *   Return any pending exceptions for the current thread and clear it as a side effect.
4362  */
4363 MonoException*
4364 mono_thread_get_and_clear_pending_exception (void)
4365 {
4366         MonoInternalThread *thread = mono_thread_internal_current ();
4367
4368         /* The thread may already be stopping */
4369         if (thread == NULL)
4370                 return NULL;
4371
4372         if (thread->interruption_requested && !is_running_protected_wrapper ()) {
4373                 return mono_thread_execute_interruption (thread);
4374         }
4375         
4376         if (thread->pending_exception) {
4377                 MonoException *exc = thread->pending_exception;
4378
4379                 thread->pending_exception = NULL;
4380                 return exc;
4381         }
4382
4383         return NULL;
4384 }
4385
4386 /*
4387  * mono_set_pending_exception:
4388  *
4389  *   Set the pending exception of the current thread to EXC.
4390  * The exception will be thrown when execution returns to managed code.
4391  */
4392 void
4393 mono_set_pending_exception (MonoException *exc)
4394 {
4395         MonoInternalThread *thread = mono_thread_internal_current ();
4396
4397         /* The thread may already be stopping */
4398         if (thread == NULL)
4399                 return;
4400
4401         MONO_OBJECT_SETREF (thread, pending_exception, exc);
4402
4403     mono_thread_request_interruption (FALSE);
4404 }
4405
4406 /**
4407  * mono_thread_interruption_request_flag:
4408  *
4409  * Returns the address of a flag that will be non-zero if an interruption has
4410  * been requested for a thread. The thread to interrupt may not be the current
4411  * thread, so an additional call to mono_thread_interruption_requested() or
4412  * mono_thread_interruption_checkpoint() is allways needed if the flag is not
4413  * zero.
4414  */
4415 gint32* mono_thread_interruption_request_flag ()
4416 {
4417         return &thread_interruption_requested;
4418 }
4419
4420 void 
4421 mono_thread_init_apartment_state (void)
4422 {
4423 #ifdef HOST_WIN32
4424         MonoInternalThread* thread = mono_thread_internal_current ();
4425
4426         /* Positive return value indicates success, either
4427          * S_OK if this is first CoInitialize call, or
4428          * S_FALSE if CoInitialize already called, but with same
4429          * threading model. A negative value indicates failure,
4430          * probably due to trying to change the threading model.
4431          */
4432         if (CoInitializeEx(NULL, (thread->apartment_state == ThreadApartmentState_STA) 
4433                         ? COINIT_APARTMENTTHREADED 
4434                         : COINIT_MULTITHREADED) < 0) {
4435                 thread->apartment_state = ThreadApartmentState_Unknown;
4436         }
4437 #endif
4438 }
4439
4440 void 
4441 mono_thread_cleanup_apartment_state (void)
4442 {
4443 #ifdef HOST_WIN32
4444         MonoInternalThread* thread = mono_thread_internal_current ();
4445
4446         if (thread && thread->apartment_state != ThreadApartmentState_Unknown) {
4447                 CoUninitialize ();
4448         }
4449 #endif
4450 }
4451
4452 void
4453 mono_thread_set_state (MonoInternalThread *thread, MonoThreadState state)
4454 {
4455         ensure_synch_cs_set (thread);
4456         
4457         EnterCriticalSection (thread->synch_cs);
4458         thread->state |= state;
4459         LeaveCriticalSection (thread->synch_cs);
4460 }
4461
4462 void
4463 mono_thread_clr_state (MonoInternalThread *thread, MonoThreadState state)
4464 {
4465         ensure_synch_cs_set (thread);
4466         
4467         EnterCriticalSection (thread->synch_cs);
4468         thread->state &= ~state;
4469         LeaveCriticalSection (thread->synch_cs);
4470 }
4471
4472 gboolean
4473 mono_thread_test_state (MonoInternalThread *thread, MonoThreadState test)
4474 {
4475         gboolean ret = FALSE;
4476
4477         ensure_synch_cs_set (thread);
4478         
4479         EnterCriticalSection (thread->synch_cs);
4480
4481         if ((thread->state & test) != 0) {
4482                 ret = TRUE;
4483         }
4484         
4485         LeaveCriticalSection (thread->synch_cs);
4486         
4487         return ret;
4488 }
4489
4490 //static MonoClassField *execution_context_field;
4491
4492 static MonoObject**
4493 get_execution_context_addr (void)
4494 {
4495         MonoDomain *domain = mono_domain_get ();
4496         guint32 offset = domain->execution_context_field_offset;
4497
4498         if (!offset) {
4499                 MonoClassField *field = mono_class_get_field_from_name (mono_defaults.thread_class, "_ec");
4500                 g_assert (field);
4501
4502                 g_assert (mono_class_try_get_vtable (domain, mono_defaults.appdomain_class));
4503
4504                 mono_domain_lock (domain);
4505                 offset = GPOINTER_TO_UINT (g_hash_table_lookup (domain->special_static_fields, field));
4506                 mono_domain_unlock (domain);
4507                 g_assert (offset);
4508
4509                 domain->execution_context_field_offset = offset;
4510         }
4511
4512         return (MonoObject**) mono_get_special_static_data (offset);
4513 }
4514
4515 MonoObject*
4516 mono_thread_get_execution_context (void)
4517 {
4518         return *get_execution_context_addr ();
4519 }
4520
4521 void
4522 mono_thread_set_execution_context (MonoObject *ec)
4523 {
4524         *get_execution_context_addr () = ec;
4525 }
4526
4527 static gboolean has_tls_get = FALSE;
4528
4529 void
4530 mono_runtime_set_has_tls_get (gboolean val)
4531 {
4532         has_tls_get = val;
4533 }
4534
4535 gboolean
4536 mono_runtime_has_tls_get (void)
4537 {
4538         return has_tls_get;
4539 }
4540
4541 int
4542 mono_thread_kill (MonoInternalThread *thread, int signal)
4543 {
4544 #ifdef __native_client__
4545         /* Workaround pthread_kill abort() in NaCl glibc. */
4546         return -1;
4547 #endif
4548 #ifdef HOST_WIN32
4549         /* Win32 uses QueueUserAPC and callers of this are guarded */
4550         g_assert_not_reached ();
4551 #else
4552 #  ifdef PTHREAD_POINTER_ID
4553         return pthread_kill ((gpointer)(gsize)(thread->tid), mono_thread_get_abort_signal ());
4554 #  else
4555 #    ifdef PLATFORM_ANDROID
4556         if (thread->android_tid != 0) {
4557                 int  ret;
4558                 int  old_errno = errno;
4559
4560                 ret = tkill ((pid_t) thread->android_tid, signal);
4561                 if (ret < 0) {
4562                         ret = errno;
4563                         errno = old_errno;
4564                 }
4565
4566                 return ret;
4567         }
4568         else
4569                 return pthread_kill (thread->tid, mono_thread_get_abort_signal ());
4570 #    else
4571         return pthread_kill (thread->tid, mono_thread_get_abort_signal ());
4572 #    endif
4573 #  endif
4574 #endif
4575 }
4576
4577 static void
4578 self_interrupt_thread (void *_unused)
4579 {
4580         MonoThreadInfo *info = mono_thread_info_current ();
4581         MonoException *exc = mono_thread_execute_interruption (mono_thread_internal_current ()); 
4582         if (exc) /*We must use _with_context since we didn't trampoline into the runtime*/
4583                 mono_raise_exception_with_context (exc, &info->suspend_state.ctx);
4584         g_assert_not_reached (); /*this MUST not happen since we can't resume from an async call*/
4585 }
4586
4587 static gboolean
4588 mono_jit_info_match (MonoJitInfo *ji, gpointer ip)
4589 {
4590         if (!ji)
4591                 return FALSE;
4592         return ji->code_start <= ip && (char*)ip < (char*)ji->code_start + ji->code_size;
4593 }
4594
4595 static gboolean
4596 last_managed (MonoStackFrameInfo *frame, MonoContext *ctx, gpointer data)
4597 {
4598         MonoJitInfo **dest = data;
4599         *dest = frame->ji;
4600         return TRUE;
4601 }
4602
4603 static MonoJitInfo*
4604 mono_thread_info_get_last_managed (MonoThreadInfo *info)
4605 {
4606         MonoJitInfo *ji = NULL;
4607         if (!info)
4608                 return NULL;
4609         mono_get_eh_callbacks ()->mono_walk_stack_with_state (last_managed, &info->suspend_state, MONO_UNWIND_SIGNAL_SAFE, &ji);
4610         return ji;
4611 }
4612
4613 static void
4614 abort_thread_internal (MonoInternalThread *thread, gboolean can_raise_exception, gboolean install_async_abort)
4615 {
4616         MonoJitInfo *ji;
4617         MonoThreadInfo *info = NULL;
4618         gboolean protected_wrapper;
4619         gboolean running_managed;
4620
4621         if (!mono_thread_info_new_interrupt_enabled ()) {
4622                 signal_thread_state_change (thread);
4623                 return;
4624         }
4625
4626         /*
4627         FIXME this is insanely broken, it doesn't cause interruption to happen
4628         synchronously since passing FALSE to mono_thread_request_interruption makes sure it returns NULL
4629         */
4630         if (thread == mono_thread_internal_current ()) {
4631                 /* Do it synchronously */
4632                 MonoException *exc = mono_thread_request_interruption (can_raise_exception); 
4633                 if (exc)
4634                         mono_raise_exception (exc);
4635 #ifndef HOST_WIN32
4636                 wapi_interrupt_thread (thread->handle);
4637 #endif
4638                 return;
4639         }
4640
4641         /*FIXME we need to check 2 conditions here, request to interrupt this thread or if the target died*/
4642         if (!(info = mono_thread_info_safe_suspend_sync ((MonoNativeThreadId)(gsize)thread->tid, TRUE))) {
4643                 return;
4644         }
4645
4646         if (mono_get_eh_callbacks ()->mono_install_handler_block_guard (&info->suspend_state)) {
4647                 mono_thread_info_resume (mono_thread_info_get_tid (info));
4648                 return;
4649         }
4650
4651         /*someone is already interrupting it*/
4652         if (InterlockedCompareExchange (&thread->interruption_requested, 1, 0) == 1) {
4653                 mono_thread_info_resume (mono_thread_info_get_tid (info));
4654                 return;
4655         }
4656         InterlockedIncrement (&thread_interruption_requested);
4657
4658         ji = mono_thread_info_get_last_managed (info);
4659         protected_wrapper = ji && mono_threads_is_critical_method (mono_jit_info_get_method (ji));
4660         running_managed = mono_jit_info_match (ji, MONO_CONTEXT_GET_IP (&info->suspend_state.ctx));
4661
4662         if (!protected_wrapper && running_managed) {
4663                 /*We are in managed code*/
4664                 /*Set the thread to call */
4665                 if (install_async_abort)
4666                         mono_thread_info_setup_async_call (info, self_interrupt_thread, NULL);
4667                 mono_thread_info_resume (mono_thread_info_get_tid (info));
4668         } else {
4669                 gpointer interrupt_handle;
4670                 /* 
4671                  * This will cause waits to be broken.
4672                  * It will also prevent the thread from entering a wait, so if the thread returns
4673                  * from the wait before it receives the abort signal, it will just spin in the wait
4674                  * functions in the io-layer until the signal handler calls QueueUserAPC which will
4675                  * make it return.
4676                  */
4677 #ifndef HOST_WIN32
4678                 interrupt_handle = wapi_prepare_interrupt_thread (thread->handle);
4679 #endif
4680                 mono_thread_info_resume (mono_thread_info_get_tid (info));
4681 #ifndef HOST_WIN32
4682                 wapi_finish_interrupt_thread (interrupt_handle);
4683 #endif
4684         }
4685         /*FIXME we need to wait for interruption to complete -- figure out how much into interruption we should wait for here*/
4686 }
4687
4688 static void
4689 transition_to_suspended (MonoInternalThread *thread)
4690 {
4691         if ((thread->state & ThreadState_SuspendRequested) == 0) {
4692                 g_assert (0); /*FIXME we should not reach this */
4693                 /*Make sure we balance the suspend count.*/
4694                 mono_thread_info_resume ((MonoNativeThreadId)(gpointer)(gsize)thread->tid);
4695         } else {
4696                 thread->state &= ~ThreadState_SuspendRequested;
4697                 thread->state |= ThreadState_Suspended;
4698                 mono_thread_info_finish_suspend ();
4699         }
4700         LeaveCriticalSection (thread->synch_cs);
4701 }
4702
4703 static void
4704 suspend_thread_internal (MonoInternalThread *thread, gboolean interrupt)
4705 {
4706         if (!mono_thread_info_new_interrupt_enabled ()) {
4707                 signal_thread_state_change (thread);
4708                 return;
4709         }
4710
4711         EnterCriticalSection (thread->synch_cs);
4712         if (thread == mono_thread_internal_current ()) {
4713                 transition_to_suspended (thread);
4714                 mono_thread_info_self_suspend ();
4715         } else {
4716                 MonoThreadInfo *info;
4717                 MonoJitInfo *ji;
4718                 gboolean protected_wrapper;
4719                 gboolean running_managed;
4720
4721                 /*A null info usually means the thread is already dead. */
4722                 if (!(info = mono_thread_info_safe_suspend_sync ((MonoNativeThreadId)(gsize)thread->tid, interrupt))) {
4723                         LeaveCriticalSection (thread->synch_cs);
4724                         return;
4725                 }
4726
4727                 ji = mono_thread_info_get_last_managed (info);
4728                 protected_wrapper = ji && mono_threads_is_critical_method (mono_jit_info_get_method (ji));
4729                 running_managed = mono_jit_info_match (ji, MONO_CONTEXT_GET_IP (&info->suspend_state.ctx));
4730
4731                 if (running_managed && !protected_wrapper) {
4732                         transition_to_suspended (thread);
4733                 } else {
4734                         gpointer interrupt_handle;
4735
4736                         if (InterlockedCompareExchange (&thread->interruption_requested, 1, 0) == 0)
4737                                 InterlockedIncrement (&thread_interruption_requested);
4738 #ifndef HOST_WIN32
4739                         if (interrupt)
4740                                 interrupt_handle = wapi_prepare_interrupt_thread (thread->handle);
4741 #endif
4742                         mono_thread_info_resume (mono_thread_info_get_tid (info));
4743 #ifndef HOST_WIN32
4744                         if (interrupt)
4745                                 wapi_finish_interrupt_thread (interrupt_handle);
4746 #endif
4747                         LeaveCriticalSection (thread->synch_cs);
4748                 }
4749         }
4750 }
4751
4752 /*This is called with @thread synch_cs held and it must release it*/
4753 static void
4754 self_suspend_internal (MonoInternalThread *thread)
4755 {
4756         if (!mono_thread_info_new_interrupt_enabled ()) {
4757                 thread->state &= ~ThreadState_SuspendRequested;
4758                 thread->state |= ThreadState_Suspended;
4759                 thread->suspend_event = CreateEvent (NULL, TRUE, FALSE, NULL);
4760                 if (thread->suspend_event == NULL) {
4761                         LeaveCriticalSection (thread->synch_cs);
4762                         return;
4763                 }
4764                 if (thread->suspended_event)
4765                         SetEvent (thread->suspended_event);
4766
4767                 LeaveCriticalSection (thread->synch_cs);
4768
4769                 if (shutting_down) {
4770                         /* After we left the lock, the runtime might shut down so everything becomes invalid */
4771                         for (;;)
4772                                 Sleep (1000);
4773                 }
4774                 
4775                 WaitForSingleObject (thread->suspend_event, INFINITE);
4776                 
4777                 EnterCriticalSection (thread->synch_cs);
4778
4779                 CloseHandle (thread->suspend_event);
4780                 thread->suspend_event = NULL;
4781                 thread->state &= ~ThreadState_Suspended;
4782         
4783                 /* The thread that requested the resume will have replaced this event
4784                  * and will be waiting for it
4785                  */
4786                 SetEvent (thread->resume_event);
4787
4788                 LeaveCriticalSection (thread->synch_cs);
4789                 return;
4790         }
4791
4792         transition_to_suspended (thread);
4793         mono_thread_info_self_suspend ();
4794 }
4795
4796 /*This is called with @thread synch_cs held and it must release it*/
4797 static gboolean
4798 resume_thread_internal (MonoInternalThread *thread)
4799 {
4800         if (!mono_thread_info_new_interrupt_enabled ()) {
4801                 thread->resume_event = CreateEvent (NULL, TRUE, FALSE, NULL);
4802                 if (thread->resume_event == NULL) {
4803                         LeaveCriticalSection (thread->synch_cs);
4804                         return FALSE;
4805                 }
4806
4807                 /* Awake the thread */
4808                 SetEvent (thread->suspend_event);
4809
4810                 LeaveCriticalSection (thread->synch_cs);
4811
4812                 /* Wait for the thread to awake */
4813                 WaitForSingleObject (thread->resume_event, INFINITE);
4814                 CloseHandle (thread->resume_event);
4815                 thread->resume_event = NULL;
4816                 return TRUE;
4817         }
4818
4819         LeaveCriticalSection (thread->synch_cs);        
4820         /* Awake the thread */
4821         if (!mono_thread_info_resume ((MonoNativeThreadId)(gpointer)(gsize)thread->tid))
4822                 return FALSE;
4823         EnterCriticalSection (thread->synch_cs);
4824         thread->state &= ~ThreadState_Suspended;
4825         LeaveCriticalSection (thread->synch_cs);
4826         return TRUE;
4827 }
4828
4829
4830 /*
4831  * mono_thread_is_foreign:
4832  * @thread: the thread to query
4833  *
4834  * This function allows one to determine if a thread was created by the mono runtime and has
4835  * a well defined lifecycle or it's a foreigh one, created by the native environment.
4836  *
4837  * Returns: true if @thread was not created by the runtime.
4838  */
4839 mono_bool
4840 mono_thread_is_foreign (MonoThread *thread)
4841 {
4842         MonoThreadInfo *info = thread->internal_thread->thread_info;
4843         return info->runtime_thread == FALSE;
4844 }