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