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