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