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