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