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