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