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