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