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