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