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