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