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