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