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