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