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