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