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