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