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