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