Merge pull request #1860 from saper/tz-fix
[mono.git] / mono / utils / mono-threads.c
1 /*
2  * mono-threads.c: Low-level threading
3  *
4  * Author:
5  *      Rodrigo Kumpera (kumpera@gmail.com)
6  *
7  * Copyright 2011 Novell, Inc (http://www.novell.com)
8  * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
9  */
10
11 #include <config.h>
12
13 #include <mono/utils/mono-compiler.h>
14 #include <mono/utils/mono-semaphore.h>
15 #include <mono/utils/mono-threads.h>
16 #include <mono/utils/mono-tls.h>
17 #include <mono/utils/hazard-pointer.h>
18 #include <mono/utils/mono-memory-model.h>
19 #include <mono/utils/mono-mmap.h>
20 #include <mono/utils/atomic.h>
21 #include <mono/utils/mono-time.h>
22
23
24 #include <errno.h>
25
26 #if defined(__MACH__)
27 #include <mono/utils/mach-support.h>
28 #endif
29
30 /*
31 Mutex that makes sure only a single thread can be suspending others.
32 Suspend is a very racy operation since it requires restarting until
33 the target thread is not on an unsafe region.
34
35 We could implement this using critical regions, but would be much much
36 harder for an operation that is hardly performance critical.
37
38 The GC has to acquire this lock before starting a STW to make sure
39 a runtime suspend won't make it wronly see a thread in a safepoint
40 when it is in fact not.
41 */
42 static MonoSemType global_suspend_semaphore;
43
44 static size_t thread_info_size;
45 static MonoThreadInfoCallbacks threads_callbacks;
46 static MonoThreadInfoRuntimeCallbacks runtime_callbacks;
47 static MonoNativeTlsKey thread_info_key, thread_exited_key;
48 #ifdef HAVE_KW_THREAD
49 static __thread guint32 tls_small_id MONO_TLS_FAST;
50 #else
51 static MonoNativeTlsKey small_id_key;
52 #endif
53 static MonoLinkedListSet thread_list;
54 static gboolean mono_threads_inited = FALSE;
55
56 static MonoSemType suspend_semaphore;
57 static size_t pending_suspends;
58 static gboolean unified_suspend_enabled;
59
60 #define mono_thread_info_run_state(info) (((MonoThreadInfo*)info)->thread_state & THREAD_STATE_MASK)
61
62 /*warn at 50 ms*/
63 #define SLEEP_DURATION_BEFORE_WARNING (10)
64 /*abort at 1 sec*/
65 #define SLEEP_DURATION_BEFORE_ABORT 200
66
67 static int suspend_posts, resume_posts, abort_posts, waits_done, pending_ops;
68
69 void
70 mono_threads_notify_initiator_of_abort (MonoThreadInfo* info)
71 {
72         THREADS_SUSPEND_DEBUG ("[INITIATOR-NOTIFY-ABORT] %p\n", mono_thread_info_get_tid (info));
73         MONO_SEM_POST (&suspend_semaphore);
74         InterlockedIncrement (&abort_posts);
75 }
76
77 void
78 mono_threads_notify_initiator_of_suspend (MonoThreadInfo* info)
79 {
80         THREADS_SUSPEND_DEBUG ("[INITIATOR-NOTIFY-SUSPEND] %p\n", mono_thread_info_get_tid (info));
81         MONO_SEM_POST (&suspend_semaphore);
82         InterlockedIncrement (&suspend_posts);
83 }
84
85 void
86 mono_threads_notify_initiator_of_resume (MonoThreadInfo* info)
87 {
88         THREADS_SUSPEND_DEBUG ("[INITIATOR-NOTIFY-RESUME] %p\n", mono_thread_info_get_tid (info));
89         MONO_SEM_POST (&suspend_semaphore);
90         InterlockedIncrement (&resume_posts);
91 }
92
93 static void
94 resume_async_suspended (MonoThreadInfo *info)
95 {
96         g_assert (mono_threads_core_begin_async_resume (info));
97 }
98
99 static void
100 resume_self_suspended (MonoThreadInfo* info)
101 {
102         THREADS_SUSPEND_DEBUG ("**BEGIN self-resume %p\n", mono_thread_info_get_tid (info));
103         MONO_SEM_POST (&info->resume_semaphore);
104 }
105
106 void
107 mono_thread_info_wait_for_resume (MonoThreadInfo* info)
108 {
109         THREADS_SUSPEND_DEBUG ("**WAIT self-resume %p\n", mono_thread_info_get_tid (info));
110         MONO_SEM_WAIT_UNITERRUPTIBLE (&info->resume_semaphore);
111 }
112
113 static void
114 resume_blocking_suspended (MonoThreadInfo* info)
115 {
116         THREADS_SUSPEND_DEBUG ("**BEGIN blocking-resume %p\n", mono_thread_info_get_tid (info));
117         MONO_SEM_POST (&info->resume_semaphore);
118 }
119
120 void
121 mono_threads_add_to_pending_operation_set (MonoThreadInfo* info)
122 {
123         THREADS_SUSPEND_DEBUG ("added %p to pending suspend\n", mono_thread_info_get_tid (info));
124         ++pending_suspends;
125         InterlockedIncrement (&pending_ops);
126 }
127
128 void
129 mono_threads_begin_global_suspend (void)
130 {
131         g_assert (pending_suspends == 0);
132         THREADS_SUSPEND_DEBUG ("------ BEGIN GLOBAL OP sp %d rp %d ap %d wd %d po %d\n", suspend_posts, resume_posts,
133                 abort_posts, waits_done, pending_ops);
134         mono_threads_core_begin_global_suspend ();
135 }
136
137 void
138 mono_threads_end_global_suspend (void) 
139 {
140         g_assert (pending_suspends == 0);
141         THREADS_SUSPEND_DEBUG ("------ END GLOBAL OP sp %d rp %d ap %d wd %d po %d\n", suspend_posts, resume_posts,
142                 abort_posts, waits_done, pending_ops);
143         mono_threads_core_end_global_suspend ();
144 }
145
146 static void
147 dump_threads (void)
148 {
149         MonoThreadInfo *info;
150         MonoThreadInfo *cur = mono_thread_info_current ();
151
152         MOSTLY_ASYNC_SAFE_PRINTF ("STATE CUE CARD: (? means a positive number, usually 1 or 2)\n");
153         MOSTLY_ASYNC_SAFE_PRINTF ("\t0x0\t- starting (GOOD, unless the thread is running managed code)\n");
154         MOSTLY_ASYNC_SAFE_PRINTF ("\t0x1\t- running (BAD, unless it's the gc thread)\n");
155         MOSTLY_ASYNC_SAFE_PRINTF ("\t0x2\t- detached (GOOD, unless the thread is running managed code)\n");
156         MOSTLY_ASYNC_SAFE_PRINTF ("\t0x?03\t- async suspended (GOOD)\n");
157         MOSTLY_ASYNC_SAFE_PRINTF ("\t0x?04\t- self suspended (GOOD)\n");
158         MOSTLY_ASYNC_SAFE_PRINTF ("\t0x?05\t- async suspend requested (BAD)\n");
159         MOSTLY_ASYNC_SAFE_PRINTF ("\t0x?06\t- self suspend requested (BAD)\n");
160         MOSTLY_ASYNC_SAFE_PRINTF ("\t0x07\t- blocking (GOOD)\n");
161         MOSTLY_ASYNC_SAFE_PRINTF ("\t0x?08\t- blocking with pending suspend (GOOD)\n");
162
163         FOREACH_THREAD_SAFE (info) {
164                 MOSTLY_ASYNC_SAFE_PRINTF ("--thread %p id %p [%p] state %x  %s\n", info, (void *) mono_thread_info_get_tid (info), (void*)(size_t)info->native_handle, info->thread_state, info == cur ? "GC INITIATOR" : "" );
165         } END_FOREACH_THREAD_SAFE
166 }
167
168 gboolean
169 mono_threads_wait_pending_operations (void)
170 {
171         int i;
172         int c = pending_suspends;
173
174         /* Wait threads to park */
175         if (pending_suspends) {
176                 MonoStopwatch suspension_time;
177                 mono_stopwatch_start (&suspension_time);
178                 THREADS_SUSPEND_DEBUG ("[INITIATOR-WAIT-COUNT] %d\n", c);
179                 for (i = 0; i < pending_suspends; ++i) {
180                         THREADS_SUSPEND_DEBUG ("[INITIATOR-WAIT-WAITING]\n");
181                         InterlockedIncrement (&waits_done);
182                         if (!MONO_SEM_TIMEDWAIT (&suspend_semaphore, SLEEP_DURATION_BEFORE_ABORT))
183                                 continue;
184                         mono_stopwatch_stop (&suspension_time);
185
186                         dump_threads ();
187
188                         MOSTLY_ASYNC_SAFE_PRINTF ("WAITING for %d threads, got %d suspended\n", (int)pending_suspends, i);
189                         g_error ("suspend_thread suspend took %d ms, which is more than the allowed %d ms", (int)mono_stopwatch_elapsed_ms (&suspension_time), SLEEP_DURATION_BEFORE_ABORT);
190                 }
191                 mono_stopwatch_stop (&suspension_time);
192                 THREADS_SUSPEND_DEBUG ("Suspending %d threads took %d ms.\n", (int)pending_suspends, (int)mono_stopwatch_elapsed_ms (&suspension_time));
193
194         }
195
196         pending_suspends = 0;
197
198         return c > 0;
199 }
200
201
202 //Thread initialization code
203
204 static void mono_threads_unregister_current_thread (MonoThreadInfo *info);
205
206 static inline void
207 mono_hazard_pointer_clear_all (MonoThreadHazardPointers *hp, int retain)
208 {
209         if (retain != 0)
210                 mono_hazard_pointer_clear (hp, 0);
211         if (retain != 1)
212                 mono_hazard_pointer_clear (hp, 1);
213         if (retain != 2)
214                 mono_hazard_pointer_clear (hp, 2);
215 }
216
217 /*
218 If return non null Hazard Pointer 1 holds the return value.
219 */
220 MonoThreadInfo*
221 mono_thread_info_lookup (MonoNativeThreadId id)
222 {
223                 MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
224
225         if (!mono_lls_find (&thread_list, hp, (uintptr_t)id)) {
226                 mono_hazard_pointer_clear_all (hp, -1);
227                 return NULL;
228         } 
229
230         mono_hazard_pointer_clear_all (hp, 1);
231         return (MonoThreadInfo *) mono_hazard_pointer_get_val (hp, 1);
232 }
233
234 static gboolean
235 mono_thread_info_insert (MonoThreadInfo *info)
236 {
237         MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
238
239         if (!mono_lls_insert (&thread_list, hp, (MonoLinkedListSetNode*)info)) {
240                 mono_hazard_pointer_clear_all (hp, -1);
241                 return FALSE;
242         } 
243
244         mono_hazard_pointer_clear_all (hp, -1);
245         return TRUE;
246 }
247
248 static gboolean
249 mono_thread_info_remove (MonoThreadInfo *info)
250 {
251         MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
252         gboolean res;
253
254         THREADS_DEBUG ("removing info %p\n", info);
255         res = mono_lls_remove (&thread_list, hp, (MonoLinkedListSetNode*)info);
256         mono_hazard_pointer_clear_all (hp, -1);
257         return res;
258 }
259
260 static void
261 free_thread_info (gpointer mem)
262 {
263         MonoThreadInfo *info = (MonoThreadInfo *) mem;
264
265         MONO_SEM_DESTROY (&info->resume_semaphore);
266         mono_threads_platform_free (info);
267
268         g_free (info);
269 }
270
271 int
272 mono_thread_info_register_small_id (void)
273 {
274         int small_id = mono_thread_small_id_alloc ();
275 #ifdef HAVE_KW_THREAD
276         tls_small_id = small_id;
277 #else
278         mono_native_tls_set_value (small_id_key, GUINT_TO_POINTER (small_id + 1));
279 #endif
280         return small_id;
281 }
282
283 static void*
284 register_thread (MonoThreadInfo *info, gpointer baseptr)
285 {
286         size_t stsize = 0;
287         guint8 *staddr = NULL;
288         int small_id = mono_thread_info_register_small_id ();
289         gboolean result;
290         mono_thread_info_set_tid (info, mono_native_thread_id_get ());
291         info->small_id = small_id;
292
293         MONO_SEM_INIT (&info->resume_semaphore, 0);
294
295         /*set TLS early so SMR works */
296         mono_native_tls_set_value (thread_info_key, info);
297
298         THREADS_DEBUG ("registering info %p tid %p small id %x\n", info, mono_thread_info_get_tid (info), info->small_id);
299
300         if (threads_callbacks.thread_register) {
301                 if (threads_callbacks.thread_register (info, baseptr) == NULL) {
302                         // g_warning ("thread registation failed\n");
303                         g_free (info);
304                         return NULL;
305                 }
306         }
307
308         mono_thread_info_get_stack_bounds (&staddr, &stsize);
309         g_assert (staddr);
310         g_assert (stsize);
311         info->stack_start_limit = staddr;
312         info->stack_end = staddr + stsize;
313
314         mono_threads_platform_register (info);
315
316         /*
317         Transition it before taking any locks or publishing itself to reduce the chance
318         of others witnessing a detached thread.
319         We can reasonably expect that until this thread gets published, no other thread will
320         try to manipulate it.
321         */
322         mono_threads_transition_attach (info);
323         mono_thread_info_suspend_lock ();
324         /*If this fail it means a given thread has been registered twice, which doesn't make sense. */
325         result = mono_thread_info_insert (info);
326         g_assert (result);
327         mono_thread_info_suspend_unlock ();
328         return info;
329 }
330
331 static void
332 unregister_thread (void *arg)
333 {
334         MonoThreadInfo *info = (MonoThreadInfo *) arg;
335         int small_id = info->small_id;
336         g_assert (info);
337
338         THREADS_DEBUG ("unregistering info %p\n", info);
339
340         mono_native_tls_set_value (thread_exited_key, GUINT_TO_POINTER (1));
341
342         mono_threads_core_unregister (info);
343
344         /*
345          * TLS destruction order is not reliable so small_id might be cleaned up
346          * before us.
347          */
348 #ifndef HAVE_KW_THREAD
349         mono_native_tls_set_value (small_id_key, GUINT_TO_POINTER (info->small_id + 1));
350 #endif
351
352         /*
353         First perform the callback that requires no locks.
354         This callback has the potential of taking other locks, so we do it before.
355         After it completes, the thread remains functional.
356         */
357         if (threads_callbacks.thread_detach)
358                 threads_callbacks.thread_detach (info);
359
360         /*
361         Since the thread info lock is taken from within blocking sections, we can't check from there, so it must be done here.
362         This ensures that we won't lose any suspend requests as a suspend initiator must hold the lock.
363         Once we're holding the suspend lock, no threads can suspend us and once we unregister, no thread can find us. 
364         */
365         MONO_PREPARE_BLOCKING
366         mono_thread_info_suspend_lock ();
367         MONO_FINISH_BLOCKING
368
369         /*
370         Now perform the callback that must be done under locks.
371         This will render the thread useless and non-suspendable, so it must
372         be done while holding the suspend lock to give no other thread chance
373         to suspend it.
374         */
375         if (threads_callbacks.thread_unregister)
376                 threads_callbacks.thread_unregister (info);
377         mono_threads_unregister_current_thread (info);
378         mono_threads_transition_detach (info);
379
380         mono_thread_info_suspend_unlock ();
381
382         /*now it's safe to free the thread info.*/
383         mono_thread_hazardous_free_or_queue (info, free_thread_info, TRUE, FALSE);
384         mono_thread_small_id_free (small_id);
385 }
386
387 static void
388 thread_exited_dtor (void *arg)
389 {
390 #if defined(__MACH__)
391         /*
392          * Since we use pthread dtors to clean up thread data, if a thread
393          * is attached to the runtime by another pthread dtor after our dtor
394          * has ran, it will never be detached, leading to various problems
395          * since the thread ids etc. will be reused while they are still in
396          * the threads hashtables etc.
397          * Dtors are called in a loop until all user tls entries are 0,
398          * but the loop has a maximum count (4), so if we set the tls
399          * variable every time, it will remain set when system tls dtors
400          * are ran. This allows mono_thread_info_is_exiting () to detect
401          * whenever the thread is exiting, even if it is executed from a
402          * system tls dtor (i.e. obj-c dealloc methods).
403          */
404         mono_native_tls_set_value (thread_exited_key, GUINT_TO_POINTER (1));
405 #endif
406 }
407
408 /**
409  * Removes the current thread from the thread list.
410  * This must be called from the thread unregister callback and nowhere else.
411  * The current thread must be passed as TLS might have already been cleaned up.
412 */
413 static void
414 mono_threads_unregister_current_thread (MonoThreadInfo *info)
415 {
416         gboolean result;
417         g_assert (mono_thread_info_get_tid (info) == mono_native_thread_id_get ());
418         result = mono_thread_info_remove (info);
419         g_assert (result);
420 }
421
422 MonoThreadInfo*
423 mono_thread_info_current_unchecked (void)
424 {
425         return (MonoThreadInfo*)mono_native_tls_get_value (thread_info_key);
426 }
427
428
429 MonoThreadInfo*
430 mono_thread_info_current (void)
431 {
432         MonoThreadInfo *info = (MonoThreadInfo*)mono_native_tls_get_value (thread_info_key);
433         if (info)
434                 return info;
435
436         info = mono_thread_info_lookup (mono_native_thread_id_get ()); /*info on HP1*/
437
438         /*
439         We might be called during thread cleanup, but we cannot be called after cleanup as happened.
440         The way to distinguish between before, during and after cleanup is the following:
441
442         -If the TLS key is set, cleanup has not begun;
443         -If the TLS key is clean, but the thread remains registered, cleanup is in progress;
444         -If the thread is nowhere to be found, cleanup has finished.
445
446         We cannot function after cleanup since there's no way to ensure what will happen.
447         */
448         g_assert (info);
449
450         /*We're looking up the current thread which will not be freed until we finish running, so no need to keep it on a HP */
451         mono_hazard_pointer_clear (mono_hazard_pointer_get (), 1);
452
453         return info;
454 }
455
456 int
457 mono_thread_info_get_small_id (void)
458 {
459 #ifdef HAVE_KW_THREAD
460         return tls_small_id;
461 #else
462         gpointer val = mono_native_tls_get_value (small_id_key);
463         if (!val)
464                 return -1;
465         return GPOINTER_TO_INT (val) - 1;
466 #endif
467 }
468
469 MonoLinkedListSet*
470 mono_thread_info_list_head (void)
471 {
472         return &thread_list;
473 }
474
475 /**
476  * mono_threads_attach_tools_thread
477  *
478  * Attach the current thread as a tool thread. DON'T USE THIS FUNCTION WITHOUT READING ALL DISCLAIMERS.
479  *
480  * A tools thread is a very special kind of thread that needs access to core runtime facilities but should
481  * not be counted as a regular thread for high order facilities such as executing managed code or accessing
482  * the managed heap.
483  *
484  * This is intended only to tools such as a profiler than needs to be able to use our lock-free support when
485  * doing things like resolving backtraces in their background processing thread.
486  */
487 void
488 mono_threads_attach_tools_thread (void)
489 {
490         int dummy = 0;
491         MonoThreadInfo *info;
492
493         /* Must only be called once */
494         g_assert (!mono_native_tls_get_value (thread_info_key));
495         
496         while (!mono_threads_inited) { 
497                 g_usleep (10);
498         }
499
500         info = mono_thread_info_attach (&dummy);
501         g_assert (info);
502
503         info->tools_thread = TRUE;
504 }
505
506 MonoThreadInfo*
507 mono_thread_info_attach (void *baseptr)
508 {
509         MonoThreadInfo *info;
510         if (!mono_threads_inited)
511         {
512 #ifdef HOST_WIN32
513                 /* This can happen from DllMain(DLL_THREAD_ATTACH) on Windows, if a
514                  * thread is created before an embedding API user initialized Mono. */
515                 THREADS_DEBUG ("mono_thread_info_attach called before mono_threads_init\n");
516                 return NULL;
517 #else
518                 g_assert (mono_threads_inited);
519 #endif
520         }
521         info = (MonoThreadInfo *) mono_native_tls_get_value (thread_info_key);
522         if (!info) {
523                 info = (MonoThreadInfo *) g_malloc0 (thread_info_size);
524                 THREADS_DEBUG ("attaching %p\n", info);
525                 if (!register_thread (info, baseptr))
526                         return NULL;
527         } else if (threads_callbacks.thread_attach) {
528                 threads_callbacks.thread_attach (info);
529         }
530         return info;
531 }
532
533 void
534 mono_thread_info_detach (void)
535 {
536         MonoThreadInfo *info;
537         if (!mono_threads_inited)
538         {
539                 /* This can happen from DllMain(THREAD_DETACH) on Windows, if a thread
540                  * is created before an embedding API user initialized Mono. */
541                 THREADS_DEBUG ("mono_thread_info_detach called before mono_threads_init\n");
542                 return;
543         }
544         info = (MonoThreadInfo *) mono_native_tls_get_value (thread_info_key);
545         if (info) {
546                 THREADS_DEBUG ("detaching %p\n", info);
547                 unregister_thread (info);
548                 mono_native_tls_set_value (thread_info_key, NULL);
549         }
550 }
551
552 /*
553  * mono_thread_info_is_exiting:
554  *
555  *   Return whenever the current thread is exiting, i.e. it is running pthread
556  * dtors.
557  */
558 gboolean
559 mono_thread_info_is_exiting (void)
560 {
561 #if defined(__MACH__)
562         if (mono_native_tls_get_value (thread_exited_key) == GUINT_TO_POINTER (1))
563                 return TRUE;
564 #endif
565         return FALSE;
566 }
567
568 void
569 mono_threads_init (MonoThreadInfoCallbacks *callbacks, size_t info_size)
570 {
571         gboolean res;
572         threads_callbacks = *callbacks;
573         thread_info_size = info_size;
574 #ifdef HOST_WIN32
575         res = mono_native_tls_alloc (&thread_info_key, NULL);
576         res = mono_native_tls_alloc (&thread_exited_key, NULL);
577 #else
578         res = mono_native_tls_alloc (&thread_info_key, (void *) unregister_thread);
579         res = mono_native_tls_alloc (&thread_exited_key, (void *) thread_exited_dtor);
580 #endif
581         g_assert (res);
582
583 #ifndef HAVE_KW_THREAD
584         res = mono_native_tls_alloc (&small_id_key, NULL);
585 #endif
586         g_assert (res);
587
588         unified_suspend_enabled = g_getenv ("MONO_ENABLE_UNIFIED_SUSPEND") != NULL || MONO_THREADS_PLATFORM_REQUIRES_UNIFIED_SUSPEND;
589
590         MONO_SEM_INIT (&global_suspend_semaphore, 1);
591         MONO_SEM_INIT (&suspend_semaphore, 0);
592
593         mono_lls_init (&thread_list, NULL);
594         mono_thread_smr_init ();
595         mono_threads_init_platform ();
596
597 #if defined(__MACH__)
598         mono_mach_init (thread_info_key);
599 #endif
600
601         mono_threads_inited = TRUE;
602
603         g_assert (sizeof (MonoNativeThreadId) <= sizeof (uintptr_t));
604 }
605
606 void
607 mono_threads_runtime_init (MonoThreadInfoRuntimeCallbacks *callbacks)
608 {
609         runtime_callbacks = *callbacks;
610 }
611
612 MonoThreadInfoRuntimeCallbacks *
613 mono_threads_get_runtime_callbacks (void)
614 {
615         return &runtime_callbacks;
616 }
617
618 /*
619 The return value is only valid until a matching mono_thread_info_resume is called
620 */
621 static MonoThreadInfo*
622 mono_thread_info_suspend_sync (MonoNativeThreadId tid, gboolean interrupt_kernel, const char **error_condition)
623 {
624         MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();      
625         MonoThreadInfo *info = mono_thread_info_lookup (tid); /*info on HP1*/
626         if (!info) {
627                 *error_condition = "Thread not found";
628                 return NULL;
629         }
630
631         switch (mono_threads_transition_request_async_suspension (info)) {
632         case AsyncSuspendAlreadySuspended:
633                 mono_hazard_pointer_clear (hp, 1); //XXX this is questionable we got to clean the suspend/resume nonsense of critical sections
634                 return info;
635         case AsyncSuspendWait:
636                 mono_threads_add_to_pending_operation_set (info);
637                 break;
638         case AsyncSuspendInitSuspend:
639                 if (!mono_threads_core_begin_async_suspend (info, interrupt_kernel)) {
640                         mono_hazard_pointer_clear (hp, 1);
641                         *error_condition = "Could not suspend thread";
642                         return NULL;
643                 }
644         }
645
646         //Wait for the pending suspend to finish
647         mono_threads_wait_pending_operations ();
648
649         if (!mono_threads_core_check_suspend_result (info)) {
650
651                 mono_hazard_pointer_clear (hp, 1);
652                 *error_condition = "Post suspend failed";
653                 return NULL;
654         }
655         return info;
656 }
657
658 /*
659 Signal that the current thread wants to be suspended.
660 This function can be called without holding the suspend lock held.
661 To finish suspending, call mono_suspend_check.
662 */
663 void
664 mono_thread_info_begin_self_suspend (void)
665 {
666         MonoThreadInfo *info = mono_thread_info_current_unchecked ();
667         if (!info)
668                 return;
669
670         THREADS_SUSPEND_DEBUG ("BEGIN SELF SUSPEND OF %p\n", info);
671         mono_threads_transition_request_self_suspension (info);
672 }
673
674 void
675 mono_thread_info_end_self_suspend (void)
676 {
677         MonoThreadInfo *info;
678
679         info = mono_thread_info_current ();
680         if (!info)
681                 return;
682         THREADS_SUSPEND_DEBUG ("FINISH SELF SUSPEND OF %p\n", info);
683
684         g_assert (mono_threads_get_runtime_callbacks ()->thread_state_init_from_sigctx (&info->thread_saved_state [SELF_SUSPEND_STATE_INDEX], NULL));
685
686         /* commit the saved state and notify others if needed */
687         switch (mono_threads_transition_state_poll (info)) {
688         case SelfSuspendResumed:
689                 return;
690         case SelfSuspendWait:
691                 mono_thread_info_wait_for_resume (info);
692                 break;
693         case SelfSuspendNotifyAndWait:
694                 mono_threads_notify_initiator_of_suspend (info);
695                 mono_thread_info_wait_for_resume (info);
696                 mono_threads_notify_initiator_of_resume (info);
697                 break;
698         }
699 }
700
701 static gboolean
702 mono_thread_info_core_resume (MonoThreadInfo *info)
703 {
704         gboolean res = FALSE;
705         if (info->create_suspended) {
706                 MonoNativeThreadId tid = mono_thread_info_get_tid (info);
707                 /* Have to special case this, as the normal suspend/resume pair are racy, they don't work if he resume is received before the suspend */
708                 info->create_suspended = FALSE;
709                 mono_threads_core_resume_created (info, tid);
710                 return TRUE;
711         }
712
713         switch (mono_threads_transition_request_resume (info)) {
714         case ResumeError:
715                 res = FALSE;
716                 break;
717         case ResumeOk:
718                 res = TRUE;
719                 break;
720         case ResumeInitSelfResume:
721                 resume_self_suspended (info);
722                 res = TRUE;
723                 break;
724         case ResumeInitAsyncResume:
725                 resume_async_suspended (info);
726                 res = TRUE;
727                 break;
728         case ResumeInitBlockingResume:
729                 resume_blocking_suspended (info);
730                 res = TRUE;
731                 break;
732         }
733
734         return res;
735 }
736
737 gboolean
738 mono_thread_info_resume (MonoNativeThreadId tid)
739 {
740         gboolean result; /* don't initialize it so the compiler can catch unitilized paths. */
741         MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
742         MonoThreadInfo *info;
743
744         THREADS_SUSPEND_DEBUG ("RESUMING tid %p\n", (void*)tid);
745
746         mono_thread_info_suspend_lock ();
747
748         info = mono_thread_info_lookup (tid); /*info on HP1*/
749         if (!info) {
750                 result = FALSE;
751                 goto cleanup;
752         }
753
754         result = mono_thread_info_core_resume (info);
755
756         //Wait for the pending resume to finish
757         mono_threads_wait_pending_operations ();
758
759 cleanup:
760         mono_thread_info_suspend_unlock ();
761         mono_hazard_pointer_clear (hp, 1);
762         return result;
763 }
764
765 gboolean
766 mono_thread_info_begin_suspend (MonoThreadInfo *info, gboolean interrupt_kernel)
767 {
768         switch (mono_threads_transition_request_async_suspension (info)) {
769         case AsyncSuspendAlreadySuspended:
770                 return TRUE;
771         case AsyncSuspendWait:
772                 mono_threads_add_to_pending_operation_set (info);
773                 return TRUE;
774         case AsyncSuspendInitSuspend:
775                 return mono_threads_core_begin_async_suspend (info, interrupt_kernel);
776         default:
777                 g_assert_not_reached ();
778         }
779 }
780
781 gboolean
782 mono_thread_info_begin_resume (MonoThreadInfo *info)
783 {
784         return mono_thread_info_core_resume (info);
785 }
786
787 /*
788 FIXME fix cardtable WB to be out of line and check with the runtime if the target is not the
789 WB trampoline. Another option is to encode wb ranges in MonoJitInfo, but that is somewhat hard.
790 */
791 static gboolean
792 is_thread_in_critical_region (MonoThreadInfo *info)
793 {
794         MonoMethod *method;
795         MonoJitInfo *ji;
796         gpointer stack_start;
797         MonoThreadUnwindState *state;
798
799         /* Are we inside a system critical region? */
800         if (info->inside_critical_region)
801                 return TRUE;
802
803         /* Are we inside a GC critical region? */
804         if (threads_callbacks.mono_thread_in_critical_region && threads_callbacks.mono_thread_in_critical_region (info)) {
805                 return TRUE;
806         }
807
808         /* The target thread might be shutting down and the domain might be null, which means no managed code left to run. */
809         state = mono_thread_info_get_suspend_state (info);
810         if (!state->unwind_data [MONO_UNWIND_DATA_DOMAIN])
811                 return FALSE;
812
813         stack_start = MONO_CONTEXT_GET_SP (&state->ctx);
814         /* altstack signal handler, sgen can't handle them, so we treat them as critical */
815         if (stack_start < info->stack_start_limit || stack_start >= info->stack_end)
816                 return TRUE;
817
818         ji = mono_jit_info_table_find (
819                 (MonoDomain *) state->unwind_data [MONO_UNWIND_DATA_DOMAIN],
820                 (char *) MONO_CONTEXT_GET_IP (&state->ctx));
821
822         if (!ji)
823                 return FALSE;
824
825         method = mono_jit_info_get_method (ji);
826
827         return threads_callbacks.mono_method_is_critical (method);
828 }
829
830 gboolean
831 mono_thread_info_in_critical_location (MonoThreadInfo *info)
832 {
833         return is_thread_in_critical_region (info);
834 }
835
836 static MonoThreadInfo*
837 suspend_sync_nolock (MonoNativeThreadId id, gboolean interrupt_kernel)
838 {
839         MonoThreadInfo *info = NULL;
840         int sleep_duration = 0;
841         for (;;) {
842                 const char *suspend_error = "Unknown error";
843                 if (!(info = mono_thread_info_suspend_sync (id, interrupt_kernel, &suspend_error))) {
844                         mono_hazard_pointer_clear (mono_hazard_pointer_get (), 1);
845                         return NULL;
846                 }
847
848                 /*WARNING: We now are in interrupt context until we resume the thread. */
849                 if (!is_thread_in_critical_region (info))
850                         break;
851
852                 if (!mono_thread_info_core_resume (info)) {
853                         mono_hazard_pointer_clear (mono_hazard_pointer_get (), 1);
854                         return NULL;
855                 }
856                 THREADS_SUSPEND_DEBUG ("RESTARTED thread tid %p\n", (void*)id);
857
858                 /* Wait for the pending resume to finish */
859                 mono_threads_wait_pending_operations ();
860
861                 if (!sleep_duration) {
862 #ifdef HOST_WIN32
863                         SwitchToThread ();
864 #else
865                         sched_yield ();
866 #endif
867                 }
868                 else {
869                         g_usleep (sleep_duration);
870                 }
871                 sleep_duration += 10;
872         }
873         return info;
874 }
875
876 void
877 mono_thread_info_safe_suspend_and_run (MonoNativeThreadId id, gboolean interrupt_kernel, MonoSuspendThreadCallback callback, gpointer user_data)
878 {
879         int result;
880         MonoThreadInfo *info = NULL;
881         MonoThreadHazardPointers *hp = mono_hazard_pointer_get ();
882
883         THREADS_SUSPEND_DEBUG ("SUSPENDING tid %p\n", (void*)id);
884         /*FIXME: unify this with self-suspend*/
885         g_assert (id != mono_native_thread_id_get ());
886
887         mono_thread_info_suspend_lock ();
888         mono_threads_begin_global_suspend ();
889
890         info = suspend_sync_nolock (id, interrupt_kernel);
891         if (!info)
892                 goto done;
893
894         switch (result = callback (info, user_data)) {
895         case MonoResumeThread:
896                 mono_hazard_pointer_set (hp, 1, info);
897                 mono_thread_info_core_resume (info);
898                 mono_threads_wait_pending_operations ();
899                 break;
900         case KeepSuspended:
901                 break;
902         default:
903                 g_error ("Invalid suspend_and_run callback return value %d", result);
904         }
905
906 done:
907         mono_hazard_pointer_clear (hp, 1);
908         mono_threads_end_global_suspend ();
909         mono_thread_info_suspend_unlock ();
910 }
911
912 /*
913 WARNING:
914 If we are trying to suspend a target that is on a critical region
915 and running a syscall we risk looping forever if @interrupt_kernel is FALSE.
916 So, be VERY carefull in calling this with @interrupt_kernel == FALSE.
917
918 Info is not put on a hazard pointer as a suspended thread cannot exit and be freed.
919
920 This function MUST be matched with mono_thread_info_finish_suspend or mono_thread_info_finish_suspend_and_resume
921 */
922 MonoThreadInfo*
923 mono_thread_info_safe_suspend_sync (MonoNativeThreadId id, gboolean interrupt_kernel)
924 {
925         MonoThreadInfo *info = NULL;
926
927         THREADS_SUSPEND_DEBUG ("SUSPENDING tid %p\n", (void*)id);
928         /*FIXME: unify this with self-suspend*/
929         g_assert (id != mono_native_thread_id_get ());
930
931         mono_thread_info_suspend_lock ();
932         mono_threads_begin_global_suspend ();
933
934         info = suspend_sync_nolock (id, interrupt_kernel);
935
936         /* XXX this clears HP 1, so we restated it again */
937         // mono_atomic_store_release (&mono_thread_info_current ()->inside_critical_region, TRUE);
938         mono_threads_end_global_suspend ();
939         mono_thread_info_suspend_unlock ();
940
941         return info;
942 }
943
944 /**
945 Inject an assynchronous call into the target thread. The target thread must be suspended and
946 only a single async call can be setup for a given suspend cycle.
947 This async call must cause stack unwinding as the current implementation doesn't save enough state
948 to resume execution of the top-of-stack function. It's an acceptable limitation since this is
949 currently used only to deliver exceptions.
950 */
951 void
952 mono_thread_info_setup_async_call (MonoThreadInfo *info, void (*target_func)(void*), void *user_data)
953 {
954         /* An async call can only be setup on an async suspended thread */
955         g_assert (mono_thread_info_run_state (info) == STATE_ASYNC_SUSPENDED);
956         /*FIXME this is a bad assert, we probably should do proper locking and fail if one is already set*/
957         g_assert (!info->async_target);
958         info->async_target = target_func;
959         /* This is not GC tracked */
960         info->user_data = user_data;
961 }
962
963 /*
964 The suspend lock is held during any suspend in progress.
965 A GC that has safepoints must take this lock as part of its
966 STW to make sure no unsafe pending suspend is in progress.   
967 */
968 void
969 mono_thread_info_suspend_lock (void)
970 {
971         MONO_SEM_WAIT_UNITERRUPTIBLE (&global_suspend_semaphore);
972 }
973
974 void
975 mono_thread_info_suspend_unlock (void)
976 {
977         MONO_SEM_POST (&global_suspend_semaphore);
978 }
979
980 /*
981  * This is a very specific function whose only purpose is to
982  * break a given thread from socket syscalls.
983  *
984  * This only exists because linux won't fail a call to connect
985  * if the underlying is closed.
986  *
987  * TODO We should cleanup and unify this with the other syscall abort
988  * facility.
989  */
990 void
991 mono_thread_info_abort_socket_syscall_for_close (MonoNativeThreadId tid)
992 {
993         MonoThreadHazardPointers *hp;
994         MonoThreadInfo *info;
995         
996         if (tid == mono_native_thread_id_get () || !mono_threads_core_needs_abort_syscall ())
997                 return;
998
999         hp = mono_hazard_pointer_get ();        
1000         info = mono_thread_info_lookup (tid); /*info on HP1*/
1001         if (!info)
1002                 return;
1003
1004         if (mono_thread_info_run_state (info) > STATE_RUNNING) {
1005                 mono_hazard_pointer_clear (hp, 1);
1006                 return;
1007         }
1008
1009         mono_thread_info_suspend_lock ();
1010         mono_threads_begin_global_suspend ();
1011
1012         mono_threads_core_abort_syscall (info);
1013         mono_threads_wait_pending_operations ();
1014
1015         mono_hazard_pointer_clear (hp, 1);
1016
1017         mono_threads_end_global_suspend ();
1018         mono_thread_info_suspend_unlock ();
1019 }
1020
1021 gboolean
1022 mono_thread_info_unified_management_enabled (void)
1023 {
1024         return unified_suspend_enabled;
1025 }
1026
1027 /*
1028  * mono_thread_info_set_is_async_context:
1029  *
1030  *   Set whenever the current thread is in an async context. Some runtime functions might behave
1031  * differently while in an async context in order to be async safe.
1032  */
1033 void
1034 mono_thread_info_set_is_async_context (gboolean async_context)
1035 {
1036         MonoThreadInfo *info = mono_thread_info_current ();
1037
1038         if (info)
1039                 info->is_async_context = async_context;
1040 }
1041
1042 gboolean
1043 mono_thread_info_is_async_context (void)
1044 {
1045         MonoThreadInfo *info = mono_thread_info_current ();
1046
1047         if (info)
1048                 return info->is_async_context;
1049         else
1050                 return FALSE;
1051 }
1052
1053 /*
1054  * mono_threads_create_thread:
1055  *
1056  *   Create a new thread executing START with argument ARG. Store its id into OUT_TID.
1057  * Returns: a windows or io-layer handle for the thread.
1058  */
1059 HANDLE
1060 mono_threads_create_thread (LPTHREAD_START_ROUTINE start, gpointer arg, guint32 stack_size, guint32 creation_flags, MonoNativeThreadId *out_tid)
1061 {
1062         return mono_threads_core_create_thread (start, arg, stack_size, creation_flags, out_tid);
1063 }
1064
1065 /*
1066  * mono_thread_info_get_stack_bounds:
1067  *
1068  *   Return the address and size of the current threads stack. Return NULL as the 
1069  * stack address if the stack address cannot be determined.
1070  */
1071 void
1072 mono_thread_info_get_stack_bounds (guint8 **staddr, size_t *stsize)
1073 {
1074         guint8 *current = (guint8 *)&stsize;
1075         mono_threads_core_get_stack_bounds (staddr, stsize);
1076         if (!*staddr)
1077                 return;
1078
1079         /* Sanity check the result */
1080         g_assert ((current > *staddr) && (current < *staddr + *stsize));
1081
1082         /* When running under emacs, sometimes staddr is not aligned to a page size */
1083         *staddr = (guint8*)((gssize)*staddr & ~(mono_pagesize () - 1));
1084 }
1085
1086 gboolean
1087 mono_thread_info_yield (void)
1088 {
1089         return mono_threads_core_yield ();
1090 }
1091
1092 gpointer
1093 mono_thread_info_tls_get (THREAD_INFO_TYPE *info, MonoTlsKey key)
1094 {
1095         return ((MonoThreadInfo*)info)->tls [key];
1096 }
1097
1098 /*
1099  * mono_threads_info_tls_set:
1100  *
1101  *   Set the TLS key to VALUE in the info structure. This can be used to obtain
1102  * values of TLS variables for threads other than the current thread.
1103  * This should only be used for infrequently changing TLS variables, and it should
1104  * be paired with setting the real TLS variable since this provides no GC tracking.
1105  */
1106 void
1107 mono_thread_info_tls_set (THREAD_INFO_TYPE *info, MonoTlsKey key, gpointer value)
1108 {
1109         ((MonoThreadInfo*)info)->tls [key] = value;
1110 }
1111
1112 /*
1113  * mono_thread_info_exit:
1114  *
1115  *   Exit the current thread.
1116  * This function doesn't return.
1117  */
1118 void
1119 mono_thread_info_exit (void)
1120 {
1121         mono_threads_core_exit (0);
1122 }
1123
1124 /*
1125  * mono_thread_info_open_handle:
1126  *
1127  *   Return a io-layer/win32 handle for the current thread.
1128  * The handle need to be closed by calling CloseHandle () when it is no
1129  * longer needed.
1130  */
1131 HANDLE
1132 mono_thread_info_open_handle (void)
1133 {
1134         return mono_threads_core_open_handle ();
1135 }
1136
1137 /*
1138  * mono_threads_open_thread_handle:
1139  *
1140  *   Return a io-layer/win32 handle for the thread identified by HANDLE/TID.
1141  * The handle need to be closed by calling CloseHandle () when it is no
1142  * longer needed.
1143  */
1144 HANDLE
1145 mono_threads_open_thread_handle (HANDLE handle, MonoNativeThreadId tid)
1146 {
1147         return mono_threads_core_open_thread_handle (handle, tid);
1148 }
1149
1150 void
1151 mono_thread_info_set_name (MonoNativeThreadId tid, const char *name)
1152 {
1153         mono_threads_core_set_name (tid, name);
1154 }
1155
1156 /*
1157  * mono_thread_info_prepare_interrupt:
1158  *
1159  *   See wapi_prepare_interrupt ().
1160  */
1161 gpointer
1162 mono_thread_info_prepare_interrupt (HANDLE thread_handle)
1163 {
1164         return mono_threads_core_prepare_interrupt (thread_handle);
1165 }
1166
1167 void
1168 mono_thread_info_finish_interrupt (gpointer wait_handle)
1169 {
1170         mono_threads_core_finish_interrupt (wait_handle);
1171 }
1172
1173 void
1174 mono_thread_info_interrupt (HANDLE thread_handle)
1175 {
1176         gpointer wait_handle;
1177
1178         wait_handle = mono_thread_info_prepare_interrupt (thread_handle);
1179         mono_thread_info_finish_interrupt (wait_handle);
1180 }
1181         
1182 void
1183 mono_thread_info_self_interrupt (void)
1184 {
1185         mono_threads_core_self_interrupt ();
1186 }
1187
1188 void
1189 mono_thread_info_clear_interruption (void)
1190 {
1191         mono_threads_core_clear_interruption ();
1192 }
1193
1194 /* info must be self or be held in a hazard pointer. */
1195 gboolean
1196 mono_threads_add_async_job (MonoThreadInfo *info, MonoAsyncJob job)
1197 {
1198         MonoAsyncJob old_job;
1199         do {
1200                 old_job = (MonoAsyncJob) info->service_requests;
1201                 if (old_job & job)
1202                         return FALSE;
1203         } while (InterlockedCompareExchange (&info->service_requests, old_job | job, old_job) != old_job);
1204         return TRUE;
1205 }
1206
1207 MonoAsyncJob
1208 mono_threads_consume_async_jobs (void)
1209 {
1210         MonoThreadInfo *info = (MonoThreadInfo*)mono_native_tls_get_value (thread_info_key);
1211
1212         if (!info)
1213                 return (MonoAsyncJob) 0;
1214
1215         return (MonoAsyncJob) InterlockedExchange (&info->service_requests, 0);
1216 }