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