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