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