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