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