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