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