#ifndef HOST_WIN32
mono_w32handle_init ();
#endif
- mono_threads_runtime_init (&ticallbacks);
+ mono_thread_info_runtime_init (&ticallbacks);
mono_install_assembly_load_hook (monodis_assembly_load_hook, NULL);
mono_install_assembly_search_hook (monodis_assembly_search_hook, NULL);
static gboolean gc_initialized = FALSE;
static mono_mutex_t mono_gc_lock;
-static void*
-boehm_thread_attach (MonoThreadInfo* info);
-static void
-boehm_thread_detach_with_lock (MonoThreadInfo *p);
-static void
-boehm_thread_detach (MonoThreadInfo *p);
static void
register_test_toggleref_callback (void);
void
mono_gc_base_init (void)
{
- MonoThreadInfoCallbacks cb;
const char *env;
if (gc_initialized)
g_strfreev (opts);
}
- memset (&cb, 0, sizeof (cb));
- cb.thread_attach = boehm_thread_attach;
- cb.thread_detach = boehm_thread_detach;
- cb.thread_detach_with_lock = boehm_thread_detach_with_lock;
- cb.mono_method_is_critical = (gboolean (*)(void *))mono_runtime_is_critical_method;
-
- mono_threads_init (&cb, sizeof (MonoThreadInfo));
+ mono_thread_callbacks_init ();
+ mono_thread_info_init (sizeof (MonoThreadInfo));
mono_os_mutex_init (&mono_gc_lock);
mono_os_mutex_init_recursive (&handle_section);
return GC_thread_is_registered ();
}
-static void*
-boehm_thread_attach (MonoThreadInfo* info)
+gpointer
+mono_gc_thread_attach (MonoThreadInfo* info)
{
struct GC_stack_base sb;
int res;
return info;
}
-static void
-boehm_thread_detach_with_lock (MonoThreadInfo *p)
+void
+mono_gc_thread_detach_with_lock (MonoThreadInfo *p)
{
MonoNativeThreadId tid;
mono_handle_stack_free (p->handle_stack);
}
-static void
-boehm_thread_detach (MonoThreadInfo *p)
+gboolean
+mono_gc_thread_in_critical_region (MonoThreadInfo *info)
{
- if (mono_thread_internal_current_is_attached ())
- mono_thread_detach_internal (mono_thread_internal_current ());
+ return FALSE;
}
gboolean
gboolean mono_gc_is_critical_method (MonoMethod *method);
+gpointer mono_gc_thread_attach (THREAD_INFO_TYPE *info);
+
+void mono_gc_thread_detach_with_lock (THREAD_INFO_TYPE *info);
+
+gboolean mono_gc_thread_in_critical_region (THREAD_INFO_TYPE *info);
+
/* If set, print debugging messages around finalizers. */
extern gboolean log_finalizers;
void
mono_gc_base_init (void)
{
- MonoThreadInfoCallbacks cb;
-
mono_counters_init ();
#ifndef HOST_WIN32
mono_w32handle_init ();
#endif
- memset (&cb, 0, sizeof (cb));
- /* TODO: This casts away an incompatible pointer type warning in the same
- manner that boehm-gc does it. This is probably worth investigating
- more carefully. */
- cb.mono_method_is_critical = (gpointer)mono_runtime_is_critical_method;
-
- mono_threads_init (&cb, sizeof (MonoThreadInfo));
+ mono_thread_callbacks_init ();
+ mono_thread_info_init (sizeof (MonoThreadInfo));
mono_thread_info_attach ();
}
return FALSE;
}
+gpointer
+mono_gc_thread_attach (MonoThreadInfo* info)
+{
+ return info;
+}
+
+void
+mono_gc_thread_detach_with_lock (MonoThreadInfo *p)
+{
+}
+
+gboolean
+mono_gc_thread_in_critical_region (MonoThreadInfo *info)
+{
+ return FALSE;
+}
+
int
mono_gc_get_aligned_size_for_allocator (int size)
{
return TRUE;
}
-
-gboolean
-mono_runtime_is_critical_method (MonoMethod *method)
-{
- return FALSE;
-}
-
/*
Coordinate the creation of all remaining TLS slots in the runtime.
No further TLS slots should be created after this function finishes.
MONO_BEGIN_DECLS
-gboolean mono_runtime_is_critical_method (MonoMethod *method);
gboolean mono_runtime_try_shutdown (void);
void mono_runtime_init_tls (void);
return sgen_has_managed_allocator ();
}
-static gboolean
-ip_in_critical_region (MonoDomain *domain, gpointer ip)
-{
- MonoJitInfo *ji;
- MonoMethod *method;
-
- /*
- * We pass false for 'try_aot' so this becomes async safe.
- * It won't find aot methods whose jit info is not yet loaded,
- * so we preload their jit info in the JIT.
- */
- ji = mono_jit_info_table_find_internal (domain, ip, FALSE, FALSE);
- if (!ji)
- return FALSE;
-
- method = mono_jit_info_get_method (ji);
-
- return mono_runtime_is_critical_method (method) || sgen_is_critical_method (method);
-}
-
gboolean
mono_gc_is_critical_method (MonoMethod *method)
{
return &gc_callbacks;
}
+gpointer
+mono_gc_thread_attach (SgenThreadInfo *info)
+{
+ return sgen_thread_attach (info);
+}
+
void
sgen_client_thread_attach (SgenThreadInfo* info)
{
info->client_info.info.handle_stack = mono_handle_stack_alloc ();
}
+void
+mono_gc_thread_detach_with_lock (SgenThreadInfo *info)
+{
+ return sgen_thread_detach_with_lock (info);
+}
+
void
sgen_client_thread_detach_with_lock (SgenThreadInfo *p)
{
}
}
-static gboolean
-thread_in_critical_region (SgenThreadInfo *info)
+gboolean
+mono_gc_thread_in_critical_region (SgenThreadInfo *info)
{
return info->client_info.in_critical_region;
}
-static void
-sgen_thread_detach (SgenThreadInfo *p)
-{
- /* If a delegate is passed to native code and invoked on a thread we dont
- * know about, marshal will register it with mono_threads_attach_coop, but
- * we have no way of knowing when that thread goes away. SGen has a TSD
- * so we assume that if the domain is still registered, we can detach
- * the thread
- */
- if (mono_thread_internal_current_is_attached ())
- mono_thread_detach_internal (mono_thread_internal_current ());
-}
-
/**
* mono_gc_is_gc_thread:
*/
void
sgen_client_init (void)
{
- MonoThreadInfoCallbacks cb;
-
- cb.thread_attach = sgen_thread_attach;
- cb.thread_detach = sgen_thread_detach;
- cb.thread_detach_with_lock = sgen_thread_detach_with_lock;
- cb.mono_thread_in_critical_region = thread_in_critical_region;
- cb.ip_in_critical_region = ip_in_critical_region;
-
- mono_threads_init (&cb, sizeof (SgenThreadInfo));
+ mono_thread_callbacks_init ();
+ mono_thread_info_init (sizeof (SgenThreadInfo));
///* Keep this the default for now */
/* Precise marking is broken on all supported targets. Disable until fixed. */
/* INFO has type MonoThreadInfo* */
typedef void (*MonoThreadNotifyPendingExcFunc) (gpointer info);
+void
+mono_thread_callbacks_init (void);
+
typedef enum {
MONO_THREAD_CREATE_FLAGS_NONE = 0x0,
MONO_THREAD_CREATE_FLAGS_THREADPOOL = 0x1,
gboolean
mono_thread_create_checked (MonoDomain *domain, gpointer func, gpointer arg, MonoError *error);
-MonoThread *
-mono_thread_attach_full (MonoDomain *domain, gboolean force_attach);
-
/* Can't include utils/mono-threads.h because of the THREAD_INFO_TYPE wizardry */
void mono_threads_add_joinable_thread (gpointer tid);
void mono_threads_join_threads (void);
g_assert (thread);
info = mono_thread_info_current ();
+ g_assert (info);
internal = thread->internal_thread;
+ g_assert (internal);
+
+ /* It is needed to store the MonoInternalThread on the MonoThreadInfo, because of the following case:
+ * - the MonoInternalThread TLS key is destroyed: set it to NULL
+ * - the MonoThreadInfo TLS key is destroyed: calls mono_thread_info_detach
+ * - it calls MonoThreadInfoCallbacks.thread_detach
+ * - mono_thread_internal_current returns NULL -> fails to detach the MonoInternalThread. */
+ mono_thread_info_set_internal_thread_gchandle (info, mono_gchandle_new ((MonoObject*) internal, FALSE));
+
internal->handle = mono_threads_open_thread_handle (info->handle);
#ifdef HOST_WIN32
internal->native_handle = OpenThread (THREAD_ALL_ACCESS, FALSE, GetCurrentThreadId ());
return (NULL != mono_thread_create_internal (domain, func, arg, MONO_THREAD_CREATE_FLAGS_NONE, error));
}
-/**
- * mono_thread_attach:
- */
-MonoThread *
-mono_thread_attach (MonoDomain *domain)
-{
- MonoThread *thread = mono_thread_attach_full (domain, FALSE);
-
- return thread;
-}
-
-MonoThread *
+static MonoThread *
mono_thread_attach_full (MonoDomain *domain, gboolean force_attach)
{
MonoInternalThread *internal;
return thread;
}
+/**
+ * mono_thread_attach:
+ */
+MonoThread *
+mono_thread_attach (MonoDomain *domain)
+{
+ return mono_thread_attach_full (domain, FALSE);
+}
+
void
mono_thread_detach_internal (MonoInternalThread *thread)
{
gboolean removed;
g_assert (thread != NULL);
+ SET_CURRENT_OBJECT (thread);
THREAD_DEBUG (g_message ("%s: mono_thread_detach for %p (%"G_GSIZE_FORMAT")", __func__, thread, (gsize)thread->tid));
SET_CURRENT_OBJECT (NULL);
mono_domain_unset ();
+ mono_thread_info_unset_internal_thread_gchandle ((MonoThreadInfo*) thread->thread_info);
+
/* Don't need to close the handle to this thread, even though we took a
* reference in mono_thread_attach (), because the GC will do it
* when the Thread object is finalised.
mono_thread_attach_cb = attach_cb;
}
+static gpointer
+thread_attach (MonoThreadInfo *info)
+{
+ return mono_gc_thread_attach (info);
+}
+
+static void
+thread_detach (MonoThreadInfo *info)
+{
+ MonoInternalThread *internal;
+ guint32 gchandle;
+
+ /* If a delegate is passed to native code and invoked on a thread we dont
+ * know about, marshal will register it with mono_threads_attach_coop, but
+ * we have no way of knowing when that thread goes away. SGen has a TSD
+ * so we assume that if the domain is still registered, we can detach
+ * the thread */
+
+ g_assert (info);
+
+ if (!mono_thread_info_try_get_internal_thread_gchandle (info, &gchandle))
+ return;
+
+ internal = (MonoInternalThread*) mono_gchandle_get_target (gchandle);
+ g_assert (internal);
+
+ mono_gchandle_free (gchandle);
+
+ mono_thread_detach_internal (internal);
+}
+
+static void
+thread_detach_with_lock (MonoThreadInfo *info)
+{
+ return mono_gc_thread_detach_with_lock (info);
+}
+
+static gboolean
+thread_in_critical_region (MonoThreadInfo *info)
+{
+ return mono_gc_thread_in_critical_region (info);
+}
+
+static gboolean
+ip_in_critical_region (MonoDomain *domain, gpointer ip)
+{
+ MonoJitInfo *ji;
+ MonoMethod *method;
+
+ /*
+ * We pass false for 'try_aot' so this becomes async safe.
+ * It won't find aot methods whose jit info is not yet loaded,
+ * so we preload their jit info in the JIT.
+ */
+ ji = mono_jit_info_table_find_internal (domain, ip, FALSE, FALSE);
+ if (!ji)
+ return FALSE;
+
+ method = mono_jit_info_get_method (ji);
+ g_assert (method);
+
+ return mono_gc_is_critical_method (method);
+}
+
+void
+mono_thread_callbacks_init (void)
+{
+ MonoThreadInfoCallbacks cb;
+
+ memset (&cb, 0, sizeof(cb));
+ cb.thread_attach = thread_attach;
+ cb.thread_detach = thread_detach;
+ cb.thread_detach_with_lock = thread_detach_with_lock;
+ cb.ip_in_critical_region = ip_in_critical_region;
+ cb.thread_in_critical_region = thread_in_critical_region;
+ mono_thread_info_callbacks_init (&cb);
+}
+
/**
* mono_thread_cleanup:
*/
if ((code = mono_aot_get_method_checked (domain, method, error))) {
MonoVTable *vtable;
- if (mono_runtime_is_critical_method (method) || mono_gc_is_critical_method (method)) {
+ if (mono_gc_is_critical_method (method)) {
/*
* The suspend code needs to be able to lookup these methods by ip in async context,
* so preload their jit info.
mono_w32handle_init ();
#endif
- mono_threads_runtime_init (&ticallbacks);
+ mono_thread_info_runtime_init (&ticallbacks);
if (g_hasenv ("MONO_DEBUG")) {
mini_parse_debug_options ();
mono_set_generic_sharing_supported (TRUE);
#endif
- mono_threads_signals_init ();
+ mono_thread_info_signals_init ();
#ifndef MONO_CROSS_COMPILE
mono_runtime_install_handlers ();
int
main (void)
{
- MonoThreadInfoCallbacks cb = { NULL };
MonoThreadInfoRuntimeCallbacks ticallbacks;
int res = 0;
CHECKED_MONO_INIT ();
- mono_threads_init (&cb, sizeof (MonoThreadInfo));
+ mono_thread_info_init (sizeof (MonoThreadInfo));
memset (&ticallbacks, 0, sizeof (ticallbacks));
ticallbacks.thread_state_init = thread_state_init;
- mono_threads_runtime_init (&ticallbacks);
+ mono_thread_info_runtime_init (&ticallbacks);
#ifndef HOST_WIN32
mono_w32handle_init ();
#endif
main (int argc, char *argv [])
{
int primes [] = { 1, 2, 3, 5, 7, 11, 13, 17 };
- MonoThreadInfoCallbacks thread_callbacks;
thread_data_t thread_data [NUM_THREADS];
int i;
- memset (&thread_callbacks, 0, sizeof (thread_callbacks));
-
mono_metadata_init ();
- mono_threads_init (&thread_callbacks, 0);
+ mono_thread_info_init (0);
mono_lls_init (&lls, free_node);
info->stackdata = g_byte_array_new ();
+ info->internal_thread_gchandle = G_MAXUINT32;
+
mono_threads_suspend_register (info);
THREADS_DEBUG ("registering info %p tid %p small id %x\n", info, mono_thread_info_get_tid (info), info->small_id);
{
/* This can happen from DllMain(DLL_THREAD_ATTACH) on Windows, if a
* thread is created before an embedding API user initialized Mono. */
- THREADS_DEBUG ("mono_thread_info_attach called before mono_threads_init\n");
+ THREADS_DEBUG ("mono_thread_info_attach called before mono_thread_info_init\n");
return NULL;
}
#endif
{
/* This can happen from DllMain(THREAD_DETACH) on Windows, if a thread
* is created before an embedding API user initialized Mono. */
- THREADS_DEBUG ("mono_thread_info_detach called before mono_threads_init\n");
+ THREADS_DEBUG ("mono_thread_info_detach called before mono_thread_info_init\n");
return;
}
#endif
}
}
+gboolean
+mono_thread_info_try_get_internal_thread_gchandle (MonoThreadInfo *info, guint32 *gchandle)
+{
+ g_assert (info);
+
+ if (info->internal_thread_gchandle == G_MAXUINT32)
+ return FALSE;
+
+ *gchandle = info->internal_thread_gchandle;
+ return TRUE;
+}
+
+void
+mono_thread_info_set_internal_thread_gchandle (MonoThreadInfo *info, guint32 gchandle)
+{
+ g_assert (info);
+ g_assert (gchandle != G_MAXUINT32);
+ info->internal_thread_gchandle = gchandle;
+}
+
+void
+mono_thread_info_unset_internal_thread_gchandle (THREAD_INFO_TYPE *info)
+{
+ g_assert (info);
+ info->internal_thread_gchandle = G_MAXUINT32;
+}
+
/*
* mono_thread_info_is_exiting:
*
#endif
void
-mono_threads_init (MonoThreadInfoCallbacks *callbacks, size_t info_size)
+mono_thread_info_init (size_t info_size)
{
gboolean res;
- threads_callbacks = *callbacks;
thread_info_size = info_size;
char *sleepLimit;
#ifdef HOST_WIN32
}
void
-mono_threads_signals_init (void)
+mono_thread_info_callbacks_init (MonoThreadInfoCallbacks *callbacks)
+{
+ threads_callbacks = *callbacks;
+}
+
+void
+mono_thread_info_signals_init (void)
{
mono_threads_suspend_init_signals ();
}
void
-mono_threads_runtime_init (MonoThreadInfoRuntimeCallbacks *callbacks)
+mono_thread_info_runtime_init (MonoThreadInfoRuntimeCallbacks *callbacks)
{
runtime_callbacks = *callbacks;
}
static gboolean
is_thread_in_critical_region (MonoThreadInfo *info)
{
- MonoMethod *method;
- MonoJitInfo *ji;
gpointer stack_start;
MonoThreadUnwindState *state;
return TRUE;
/* Are we inside a GC critical region? */
- if (threads_callbacks.mono_thread_in_critical_region && threads_callbacks.mono_thread_in_critical_region (info)) {
+ if (threads_callbacks.thread_in_critical_region && threads_callbacks.thread_in_critical_region (info)) {
return TRUE;
}
if (threads_callbacks.ip_in_critical_region)
return threads_callbacks.ip_in_critical_region ((MonoDomain *) state->unwind_data [MONO_UNWIND_DATA_DOMAIN], (char *) MONO_CONTEXT_GET_IP (&state->ctx));
- ji = mono_jit_info_table_find (
- (MonoDomain *) state->unwind_data [MONO_UNWIND_DATA_DOMAIN],
- (char *) MONO_CONTEXT_GET_IP (&state->ctx));
-
- if (!ji)
- return FALSE;
-
- method = mono_jit_info_get_method (ji);
-
- return threads_callbacks.mono_method_is_critical (method);
+ return FALSE;
}
gboolean
/* Stack mark for targets that explicitly require one */
gpointer stack_mark;
+
+ /* GCHandle to MonoInternalThread */
+ guint32 internal_thread_gchandle;
} MonoThreadInfo;
typedef struct {
SMR remains functional as its small_id has not been reclaimed.
*/
void (*thread_detach_with_lock)(THREAD_INFO_TYPE *info);
- gboolean (*mono_method_is_critical) (void *method);
gboolean (*ip_in_critical_region) (MonoDomain *domain, gpointer ip);
- gboolean (*mono_thread_in_critical_region) (THREAD_INFO_TYPE *info);
+ gboolean (*thread_in_critical_region) (THREAD_INFO_TYPE *info);
} MonoThreadInfoCallbacks;
typedef struct {
* a single block with info from both camps.
*/
void
-mono_threads_init (MonoThreadInfoCallbacks *callbacks, size_t thread_info_size);
+mono_thread_info_init (size_t thread_info_size);
+
+void
+mono_thread_info_callbacks_init (MonoThreadInfoCallbacks *callbacks);
void
-mono_threads_signals_init (void);
+mono_thread_info_signals_init (void);
void
-mono_threads_runtime_init (MonoThreadInfoRuntimeCallbacks *callbacks);
+mono_thread_info_runtime_init (MonoThreadInfoRuntimeCallbacks *callbacks);
MonoThreadInfoRuntimeCallbacks *
mono_threads_get_runtime_callbacks (void);
MONO_API void
mono_thread_info_detach (void);
+gboolean
+mono_thread_info_try_get_internal_thread_gchandle (THREAD_INFO_TYPE *info, guint32 *gchandle);
+
+void
+mono_thread_info_set_internal_thread_gchandle (THREAD_INFO_TYPE *info, guint32 gchandle);
+
+void
+mono_thread_info_unset_internal_thread_gchandle (THREAD_INFO_TYPE *info);
+
gboolean
mono_thread_info_is_exiting (void);
#ifndef HOST_WIN32
mono_w32handle_init ();
#endif
- mono_threads_runtime_init (&ticallbacks);
+ mono_thread_info_runtime_init (&ticallbacks);
mono_metadata_init ();
mono_images_init ();