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