#define GET_CURRENT_OBJECT() tls_current_object
#else
#define SET_CURRENT_OBJECT(x) TlsSetValue (current_object_key, x)
-#define GET_CURRENT_OBJECT() (MonoThread*) TlsGetValue (current_object_key)
+#define GET_CURRENT_OBJECT() (MonoInternalThread*) TlsGetValue (current_object_key)
#endif
/* function called at thread start */
static MonoThread*
create_thread_object (MonoDomain *domain)
{
- MonoVTable *vt = mono_class_vtable (mono_get_root_domain (), mono_defaults.thread_class);
+ MonoVTable *vt = mono_class_vtable (domain, mono_defaults.thread_class);
return (MonoThread*)mono_gc_alloc_mature (vt);
}
MONO_OBJECT_SETREF (thread, root_domain_thread, candidate);
}
-static guint32 WINAPI start_wrapper(void *data)
+static guint32 WINAPI start_wrapper_internal(void *data)
{
struct StartInfo *start_info=(struct StartInfo *)data;
guint32 (*start_func)(void *);
void *start_arg;
gsize tid;
- MonoThread *thread=start_info->obj;
- MonoInternalThread *internal = thread->internal_thread;
+ /*
+ * We don't create a local to hold start_info->obj, so hopefully it won't get pinned during a
+ * GC stack walk.
+ */
+ MonoInternalThread *internal = start_info->obj->internal_thread;
MonoObject *start_delegate = start_info->delegate;
+ MonoDomain *domain = start_info->obj->obj.vtable->domain;
THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") Start wrapper", __func__, GetCurrentThreadId ()));
mono_monitor_init_tls ();
/* Every thread references the appdomain which created it */
- mono_thread_push_appdomain_ref (thread->obj.vtable->domain);
+ mono_thread_push_appdomain_ref (domain);
- if (!mono_domain_set (thread->obj.vtable->domain, FALSE)) {
+ if (!mono_domain_set (domain, FALSE)) {
/* No point in raising an appdomain_unloaded exception here */
/* FIXME: Cleanup here */
mono_thread_pop_appdomain_ref ();
/* We have to do this here because mono_thread_new_init()
requires that root_domain_thread is set up. */
thread_adjust_static_data (internal);
- init_root_domain_thread (internal, thread);
+ init_root_domain_thread (internal, start_info->obj);
/* This MUST be called before any managed code can be
* executed, as it calls the callback function that (for the
}
mono_threads_lock ();
- mono_g_hash_table_remove (thread_start_args, thread);
+ mono_g_hash_table_remove (thread_start_args, start_info->obj);
mono_threads_unlock ();
+ mono_thread_set_execution_context (start_info->obj->ec_to_set);
+ start_info->obj->ec_to_set = NULL;
+
g_free (start_info);
#ifdef DEBUG
g_message ("%s: start_wrapper for %"G_GSIZE_FORMAT, __func__,
thread->tid);
#endif
- mono_thread_set_execution_context (thread->ec_to_set);
- thread->ec_to_set = NULL;
-
/*
* Call this after calling start_notify, since the profiler callback might want
* to lock the thread, and the lock is held by thread_start () which waits for
return(0);
}
+static guint32 WINAPI start_wrapper(void *data)
+{
+#ifdef HAVE_SGEN_GC
+ volatile int dummy;
+
+ /* Avoid scanning the frames above this frame during a GC */
+ mono_gc_set_stack_end ((void*)&dummy);
+#endif
+
+ return start_wrapper_internal (data);
+}
+
void mono_thread_new_init (intptr_t tid, gpointer stack_start, gpointer func)
{
if (mono_thread_start_cb) {
/* FIXME: exitContext isnt documented */
gint32 ves_icall_System_Threading_WaitHandle_WaitAny_internal(MonoArray *mono_handles, gint32 ms, gboolean exitContext)
{
- HANDLE *handles;
+ HANDLE handles [MAXIMUM_WAIT_OBJECTS];
guint32 numhandles;
guint32 ret;
guint32 i;
mono_thread_current_check_pending_interrupt ();
numhandles = mono_array_length(mono_handles);
- handles = g_new0(HANDLE, numhandles);
+ if (numhandles > MAXIMUM_WAIT_OBJECTS)
+ return WAIT_FAILED;
for(i = 0; i < numhandles; i++) {
waitHandle = mono_array_get(mono_handles, MonoObject*, i);
} while (ms == -1 || ms > 0);
mono_thread_clr_state (thread, ThreadState_WaitSleepJoin);
-
- g_free(handles);
THREAD_WAIT_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") returning %d", __func__, GetCurrentThreadId (), ret));
LeaveCriticalSection (current_thread->synch_cs);
}
+ /*since we're killing the thread, unset the current domain.*/
+ mono_domain_unset ();
+
/* Wake up other threads potentially waiting for us */
ExitThread (0);
} else {
}
gpointer
-mono_get_special_static_data (guint32 offset)
+mono_get_special_static_data_for_thread (MonoInternalThread *thread, guint32 offset)
{
/* The high bit means either thread (0) or static (1) data. */
idx = (offset >> 24) - 1;
if (static_type == 0) {
- return get_thread_static_data (mono_thread_internal_current (), offset);
+ return get_thread_static_data (thread, offset);
} else {
/* Allocate static data block under demand, since we don't have a list
// of contexts
}
}
+gpointer
+mono_get_special_static_data (guint32 offset)
+{
+ return mono_get_special_static_data_for_thread (mono_thread_internal_current (), offset);
+}
+
typedef struct {
guint32 offset;
guint32 size;