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