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