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