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