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