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