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