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