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