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