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