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