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