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