#include <config.h>
+/* enable pthread extensions */
+#ifdef TARGET_MACH
+#define _DARWIN_C_SOURCE
+#endif
+
#include <mono/utils/mono-compiler.h>
#include <mono/utils/mono-semaphore.h>
#include <mono/utils/mono-threads.h>
#include <mono/utils/mono-mmap.h>
#include <mono/utils/atomic.h>
#include <mono/utils/mono-time.h>
+#include <mono/utils/mono-lazy-init.h>
#include <errno.h>
MOSTLY_ASYNC_SAFE_PRINTF ("\t0x?08\t- blocking with pending suspend (GOOD)\n");
FOREACH_THREAD_SAFE (info) {
+#ifdef TARGET_MACH
+ char thread_name [256] = { 0 };
+ pthread_getname_np (mono_thread_info_get_tid (info), thread_name, 255);
+
+ MOSTLY_ASYNC_SAFE_PRINTF ("--thread %p id %p [%p] (%s) state %x %s\n", info, (void *) mono_thread_info_get_tid (info), (void*)(size_t)info->native_handle, thread_name, info->thread_state, info == cur ? "GC INITIATOR" : "" );
+#else
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" : "" );
+#endif
+
} END_FOREACH_THREAD_SAFE
}
info->stack_start_limit = staddr;
info->stack_end = staddr + stsize;
+ info->stackdata = g_byte_array_new ();
+
mono_threads_platform_register (info);
/*
mono_thread_info_suspend_unlock ();
+ g_byte_array_free (info->stackdata, /*free_segment=*/TRUE);
+
/*now it's safe to free the thread info.*/
mono_thread_hazardous_free_or_queue (info, free_thread_info, TRUE, FALSE);
mono_thread_small_id_free (small_id);
mono_lls_init (&thread_list, NULL);
mono_thread_smr_init ();
mono_threads_init_platform ();
+ mono_threads_init_abort_syscall ();
#if defined(__MACH__)
mono_mach_init (thread_info_key);
if (!info)
return;
- if (mono_thread_info_run_state (info) > STATE_RUNNING) {
+ if (mono_thread_info_run_state (info) == STATE_DETACHED) {
mono_hazard_pointer_clear (hp, 1);
return;
}
{
return mono_threads_core_yield ();
}
+static mono_lazy_init_t sleep_init = MONO_LAZY_INIT_STATUS_NOT_INITIALIZED;
+static mono_mutex_t sleep_mutex;
+static mono_cond_t sleep_cond;
+
+static void
+sleep_initialize (void)
+{
+ mono_mutex_init (&sleep_mutex);
+ mono_cond_init (&sleep_cond, NULL);
+}
+
+static void
+sleep_interrupt (gpointer data)
+{
+ mono_mutex_lock (&sleep_mutex);
+ mono_cond_broadcast (&sleep_cond);
+ mono_mutex_unlock (&sleep_mutex);
+}
+
+static inline guint32
+sleep_interruptable (guint32 ms, gboolean *alerted)
+{
+ guint32 start, now, end;
+
+ g_assert (INFINITE == G_MAXUINT32);
+
+ g_assert (alerted);
+ *alerted = FALSE;
+
+ start = mono_msec_ticks ();
+
+ if (start < G_MAXUINT32 - ms) {
+ end = start + ms;
+ } else {
+ /* start + ms would overflow guint32 */
+ end = G_MAXUINT32;
+ }
+
+ mono_lazy_initialize (&sleep_init, sleep_initialize);
+
+ mono_mutex_lock (&sleep_mutex);
+
+ for (now = mono_msec_ticks (); ms == INFINITE || now - start < ms; now = mono_msec_ticks ()) {
+ mono_thread_info_install_interrupt (sleep_interrupt, NULL, alerted);
+ if (*alerted) {
+ mono_mutex_unlock (&sleep_mutex);
+ return WAIT_IO_COMPLETION;
+ }
+
+ if (ms < INFINITE)
+ mono_cond_timedwait_ms (&sleep_cond, &sleep_mutex, end - now);
+ else
+ mono_cond_wait (&sleep_cond, &sleep_mutex);
+
+ mono_thread_info_uninstall_interrupt (alerted);
+ if (*alerted) {
+ mono_mutex_unlock (&sleep_mutex);
+ return WAIT_IO_COMPLETION;
+ }
+ }
+
+ mono_mutex_unlock (&sleep_mutex);
+
+ return 0;
+}
+
+gint
+mono_thread_info_sleep (guint32 ms, gboolean *alerted)
+{
+ if (ms == 0) {
+ MonoThreadInfo *info;
+
+ mono_thread_info_yield ();
+
+ info = mono_thread_info_current ();
+ if (info && mono_thread_info_is_interrupt_state (info))
+ return WAIT_IO_COMPLETION;
+
+ return 0;
+ }
+
+ if (alerted)
+ return sleep_interruptable (ms, alerted);
+
+ if (ms == INFINITE) {
+ do {
+#ifdef HOST_WIN32
+ Sleep (G_MAXUINT32);
+#else
+ sleep (G_MAXUINT32);
+#endif
+ } while (1);
+ } else {
+ int ret;
+#if defined (__linux__) && !defined(PLATFORM_ANDROID)
+ struct timespec start, target;
+
+ /* Use clock_nanosleep () to prevent time drifting problems when nanosleep () is interrupted by signals */
+ ret = clock_gettime (CLOCK_MONOTONIC, &start);
+ g_assert (ret == 0);
+
+ target = start;
+ target.tv_sec += ms / 1000;
+ target.tv_nsec += (ms % 1000) * 1000000;
+ if (target.tv_nsec > 999999999) {
+ target.tv_nsec -= 999999999;
+ target.tv_sec ++;
+ }
+
+ do {
+ ret = clock_nanosleep (CLOCK_MONOTONIC, TIMER_ABSTIME, &target, NULL);
+ } while (ret != 0);
+#elif HOST_WIN32
+ Sleep (ms);
+#else
+ struct timespec req, rem;
+
+ req.tv_sec = ms / 1000;
+ req.tv_nsec = (ms % 1000) * 1000000;
+
+ do {
+ memset (&rem, 0, sizeof (rem));
+ ret = nanosleep (&req, &rem);
+ } while (ret != 0);
+#endif /* __linux__ */
+ }
+
+ return 0;
+}
gpointer
mono_thread_info_tls_get (THREAD_INFO_TYPE *info, MonoTlsKey key)