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