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