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