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