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