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