static void
mono_threads_lock (void)
{
- MONO_TRY_BLOCKING
+ MONO_TRY_BLOCKING;
mono_locks_acquire (&threads_mutex, ThreadsLock);
- MONO_FINISH_TRY_BLOCKING
+ MONO_FINISH_TRY_BLOCKING;
}
static void
g_assert (thread->synch_cs);
- MONO_TRY_BLOCKING
+ MONO_TRY_BLOCKING;
mono_mutex_lock (thread->synch_cs);
- MONO_FINISH_TRY_BLOCKING
+ MONO_FINISH_TRY_BLOCKING;
}
static inline void
*/
if (thread_start_args == NULL) {
MONO_GC_REGISTER_ROOT_FIXED (thread_start_args);
- thread_start_args = mono_g_hash_table_new (NULL, NULL);
+ thread_start_args = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_CONSERVATIVE_GC);
}
mono_g_hash_table_insert (thread_start_args, thread, start_info->start_arg);
if (threads_starting_up == NULL) {
*/
create_flags = CREATE_SUSPENDED;
- MONO_PREPARE_BLOCKING
+ MONO_PREPARE_BLOCKING;
thread_handle = mono_threads_create_thread ((LPTHREAD_START_ROUTINE)start_wrapper, start_info,
stack_size, create_flags, &tid);
- MONO_FINISH_BLOCKING
+ MONO_FINISH_BLOCKING;
if (thread_handle == NULL) {
/* The thread couldn't be created, so throw an exception */
if (!handle_store (thread, FALSE))
return FALSE;
- MONO_PREPARE_BLOCKING
+ MONO_PREPARE_BLOCKING;
mono_thread_info_resume (tid);
- MONO_FINISH_BLOCKING
+ MONO_FINISH_BLOCKING;
if (internal->start_notify) {
/*
*/
THREAD_DEBUG (g_message ("%s: (%"G_GSIZE_FORMAT") waiting for thread %p (%"G_GSIZE_FORMAT") to start", __func__, GetCurrentThreadId (), internal, (gsize)internal->tid));
- MONO_PREPARE_BLOCKING
+ MONO_PREPARE_BLOCKING;
WaitForSingleObjectEx (internal->start_notify, INFINITE, FALSE);
- MONO_FINISH_BLOCKING
+ MONO_FINISH_BLOCKING;
CloseHandle (internal->start_notify);
internal->start_notify = NULL;
}
void
-ves_icall_System_Threading_Thread_ConstructInternalThread (MonoThread *this)
+ves_icall_System_Threading_Thread_ConstructInternalThread (MonoThread *this_obj)
{
MonoInternalThread *internal = create_internal_thread ();
internal->state = ThreadState_Unstarted;
- InterlockedCompareExchangePointer ((gpointer)&this->internal_thread, internal, NULL);
+ InterlockedCompareExchangePointer ((gpointer)&this_obj->internal_thread, internal, NULL);
}
HANDLE
-ves_icall_System_Threading_Thread_Thread_internal (MonoThread *this,
+ves_icall_System_Threading_Thread_Thread_internal (MonoThread *this_obj,
MonoObject *start)
{
StartInfo *start_info;
MonoInternalThread *internal;
gboolean res;
- THREAD_DEBUG (g_message("%s: Trying to start a new thread: this (%p) start (%p)", __func__, this, start));
+ THREAD_DEBUG (g_message("%s: Trying to start a new thread: this (%p) start (%p)", __func__, this_obj, start));
- if (!this->internal_thread)
- ves_icall_System_Threading_Thread_ConstructInternalThread (this);
- internal = this->internal_thread;
+ if (!this_obj->internal_thread)
+ ves_icall_System_Threading_Thread_ConstructInternalThread (this_obj);
+ internal = this_obj->internal_thread;
LOCK_THREAD (internal);
if ((internal->state & ThreadState_Aborted) != 0) {
UNLOCK_THREAD (internal);
- return this;
+ return this_obj;
}
/* This is freed in start_wrapper */
start_info = g_new0 (StartInfo, 1);
start_info->func = NULL;
- start_info->start_arg = this->start_obj; /* FIXME: GC object stored in unmanaged memory */
+ start_info->start_arg = this_obj->start_obj; /* FIXME: GC object stored in unmanaged memory */
start_info->delegate = start;
- start_info->obj = this;
- g_assert (this->obj.vtable->domain == mono_domain_get ());
+ start_info->obj = this_obj;
+ g_assert (this_obj->obj.vtable->domain == mono_domain_get ());
- res = create_thread (this, internal, start_info, FALSE, 0, FALSE);
+ res = create_thread (this_obj, internal, start_info, FALSE, 0, FALSE);
if (!res) {
UNLOCK_THREAD (internal);
return NULL;
* This is called from the finalizer of the internal thread object.
*/
void
-ves_icall_System_Threading_InternalThread_Thread_free_internal (MonoInternalThread *this, HANDLE thread)
+ves_icall_System_Threading_InternalThread_Thread_free_internal (MonoInternalThread *this_obj, HANDLE thread)
{
THREAD_DEBUG (g_message ("%s: Closing thread %p, handle %p", __func__, this, thread));
if (thread)
CloseHandle (thread);
- if (this->synch_cs) {
- mono_mutex_t *synch_cs = this->synch_cs;
- this->synch_cs = NULL;
+ if (this_obj->synch_cs) {
+ mono_mutex_t *synch_cs = this_obj->synch_cs;
+ this_obj->synch_cs = NULL;
mono_mutex_destroy (synch_cs);
g_free (synch_cs);
}
- if (this->name) {
- void *name = this->name;
- this->name = NULL;
+ if (this_obj->name) {
+ void *name = this_obj->name;
+ this_obj->name = NULL;
g_free (name);
}
}
while (TRUE) {
mono_thread_set_state (thread, ThreadState_WaitSleepJoin);
- MONO_PREPARE_BLOCKING
+ MONO_PREPARE_BLOCKING;
res = SleepEx(ms,TRUE);
- MONO_FINISH_BLOCKING
+ MONO_FINISH_BLOCKING;
mono_thread_clr_state (thread, ThreadState_WaitSleepJoin);
}
void
-ves_icall_System_Threading_Thread_SetPriority (MonoThread *this, int priority)
+ves_icall_System_Threading_Thread_SetPriority (MonoThread *this_obj, int priority)
{
}
}
gboolean
-ves_icall_System_Threading_Thread_Join_internal(MonoThread *this, int ms)
+ves_icall_System_Threading_Thread_Join_internal(MonoThread *this_obj, int ms)
{
- MonoInternalThread *this_obj = this->internal_thread;
- HANDLE thread = this_obj->handle;
+ MonoInternalThread *thread = this_obj->internal_thread;
+ HANDLE handle = thread->handle;
MonoInternalThread *cur_thread = mono_thread_internal_current ();
gboolean ret;
mono_thread_current_check_pending_interrupt ();
- LOCK_THREAD (this_obj);
+ LOCK_THREAD (thread);
- if ((this_obj->state & ThreadState_Unstarted) != 0) {
- UNLOCK_THREAD (this_obj);
+ if ((thread->state & ThreadState_Unstarted) != 0) {
+ UNLOCK_THREAD (thread);
mono_set_pending_exception (mono_get_exception_thread_state ("Thread has not been started."));
return FALSE;
}
- UNLOCK_THREAD (this_obj);
+ UNLOCK_THREAD (thread);
if(ms== -1) {
ms=INFINITE;
}
- THREAD_DEBUG (g_message ("%s: joining thread handle %p, %d ms", __func__, thread, ms));
+ THREAD_DEBUG (g_message ("%s: joining thread handle %p, %d ms", __func__, handle, ms));
mono_thread_set_state (cur_thread, ThreadState_WaitSleepJoin);
- MONO_PREPARE_BLOCKING
- ret=WaitForSingleObjectEx (thread, ms, TRUE);
- MONO_FINISH_BLOCKING
+ MONO_PREPARE_BLOCKING;
+ ret=WaitForSingleObjectEx (handle, ms, TRUE);
+ MONO_FINISH_BLOCKING;
mono_thread_clr_state (cur_thread, ThreadState_WaitSleepJoin);
start = (ms == -1) ? 0 : mono_100ns_ticks ();
do {
- MONO_PREPARE_BLOCKING
+ MONO_PREPARE_BLOCKING;
if (multiple)
ret = WaitForMultipleObjectsEx (numhandles, handles, waitall, wait, alertable);
else
ret = WaitForSingleObjectEx (handles [0], ms, alertable);
- MONO_FINISH_BLOCKING
+ MONO_FINISH_BLOCKING;
if (ret != WAIT_IO_COMPLETION)
break;
}
/* FIXME: exitContext isnt documented */
-gboolean ves_icall_System_Threading_WaitHandle_WaitOne_internal(MonoObject *this, HANDLE handle, gint32 ms, gboolean exitContext)
+gboolean ves_icall_System_Threading_WaitHandle_WaitOne_internal(MonoObject *this_obj, HANDLE handle, gint32 ms, gboolean exitContext)
{
guint32 ret;
MonoInternalThread *thread = mono_thread_internal_current ();
mono_thread_set_state (thread, ThreadState_WaitSleepJoin);
- MONO_PREPARE_BLOCKING
+ MONO_PREPARE_BLOCKING;
ret = SignalObjectAndWait (toSignal, toWait, ms, TRUE);
- MONO_FINISH_BLOCKING
+ MONO_FINISH_BLOCKING;
mono_thread_clr_state (thread, ThreadState_WaitSleepJoin);
return state;
}
-void ves_icall_System_Threading_Thread_Interrupt_internal (MonoThread *this)
+void ves_icall_System_Threading_Thread_Interrupt_internal (MonoThread *this_obj)
{
MonoInternalThread *current;
gboolean throw;
- MonoInternalThread *this_obj = this->internal_thread;
+ MonoInternalThread *thread = this_obj->internal_thread;
- LOCK_THREAD (this_obj);
+ LOCK_THREAD (thread);
current = mono_thread_internal_current ();
- this_obj->thread_interrupt_requested = TRUE;
- throw = current != this_obj && (this_obj->state & ThreadState_WaitSleepJoin);
+ thread->thread_interrupt_requested = TRUE;
+ throw = current != thread && (thread->state & ThreadState_WaitSleepJoin);
- UNLOCK_THREAD (this_obj);
+ UNLOCK_THREAD (thread);
if (throw) {
- abort_thread_internal (this_obj, TRUE, FALSE);
+ abort_thread_internal (thread, TRUE, FALSE);
}
}
}
void
-ves_icall_System_Threading_Thread_ResetAbort (MonoThread *this)
+ves_icall_System_Threading_Thread_ResetAbort (MonoThread *this_obj)
{
MonoInternalThread *thread = mono_thread_internal_current ();
gboolean was_aborting;
}
MonoObject*
-ves_icall_System_Threading_Thread_GetAbortExceptionState (MonoThread *this)
+ves_icall_System_Threading_Thread_GetAbortExceptionState (MonoThread *this_obj)
{
- MonoInternalThread *thread = this->internal_thread;
+ MonoInternalThread *thread = this_obj->internal_thread;
MonoObject *state, *deserialized = NULL, *exc;
MonoDomain *domain;
}
void
-ves_icall_System_Threading_Thread_Suspend (MonoThread *this)
+ves_icall_System_Threading_Thread_Suspend (MonoThread *this_obj)
{
- if (!mono_thread_suspend (this->internal_thread)) {
+ if (!mono_thread_suspend (this_obj->internal_thread)) {
mono_set_pending_exception (mono_get_exception_thread_state ("Thread has not been started, or is dead."));
return;
}
g_hash_table_insert (contexts, gch, gch);
mono_threads_unlock ();
+
+ mono_profiler_context_loaded (ctx);
+}
+
+void
+ves_icall_System_Runtime_Remoting_Contexts_Context_ReleaseContext (MonoAppContext *ctx)
+{
+ /*
+ * NOTE: Since finalizers are unreliable for the purposes of ensuring
+ * cleanup in exceptional circumstances, we don't actually do any
+ * cleanup work here. We instead do this when we iterate the `contexts`
+ * hash table. The only purpose of this finalizer, at the moment, is to
+ * notify the profiler.
+ */
+
+ //g_print ("Releasing context %d in domain %d\n", ctx->context_id, ctx->domain_id);
+
+ mono_profiler_context_unloaded (ctx);
}
void
THREAD_DEBUG (g_message("%s: %d threads to wait for in this batch", __func__, wait->num));
- MONO_PREPARE_BLOCKING
+ MONO_PREPARE_BLOCKING;
ret=WaitForMultipleObjectsEx(wait->num, wait->handles, TRUE, timeout, TRUE);
- MONO_FINISH_BLOCKING
+ MONO_FINISH_BLOCKING;
if(ret==WAIT_FAILED) {
/* See the comment in build_wait_tids() */
count++;
}
- MONO_PREPARE_BLOCKING
+ MONO_PREPARE_BLOCKING;
ret=WaitForMultipleObjectsEx (count, wait->handles, FALSE, timeout, TRUE);
- MONO_FINISH_BLOCKING
+ MONO_FINISH_BLOCKING;
if(ret==WAIT_FAILED) {
/* See the comment in build_wait_tids() */
{
GString *p = (GString*)data;
MonoMethod *method = NULL;
- if (frame->ji)
+ if (frame->type == FRAME_TYPE_MANAGED)
method = mono_jit_info_get_method (frame->ji);
if (method) {
mono_threads_unlock ();
}
+/*
+ * LOCKING: requires that threads_mutex is held
+ */
static void
context_adjust_static_data (MonoAppContext *ctx)
{
- mono_threads_lock ();
-
if (context_static_info.offset || context_static_info.idx > 0) {
guint32 offset = MAKE_SPECIAL_STATIC_OFFSET (context_static_info.idx, context_static_info.offset, 0);
mono_alloc_static_data (&ctx->static_data, offset, FALSE);
}
-
- mono_threads_unlock ();
}
/*
WaitForSingleObjectEx (GetCurrentThread(), 0, TRUE);
#endif
InterlockedDecrement (&thread_interruption_requested);
+
/* Clear the interrupted flag of the thread so it can wait again */
- mono_thread_info_clear_interruption ();
+ mono_thread_info_clear_self_interrupt ();
}
if ((thread->state & ThreadState_AbortRequested) != 0) {
typedef struct {
MonoInternalThread *thread;
gboolean install_async_abort;
- gpointer interrupt_handle;
+ MonoThreadInfoInterruptToken *interrupt_token;
} AbortThreadData;
static SuspendThreadResult
InterlockedIncrement (&thread_interruption_requested);
ji = mono_thread_info_get_last_managed (info);
- protected_wrapper = ji && mono_threads_is_critical_method (mono_jit_info_get_method (ji));
+ protected_wrapper = ji && !ji->is_trampoline && !ji->async && mono_threads_is_critical_method (mono_jit_info_get_method (ji));
running_managed = mono_jit_info_match (ji, MONO_CONTEXT_GET_IP (&mono_thread_info_get_suspend_state (info)->ctx));
if (!protected_wrapper && running_managed) {
* functions in the io-layer until the signal handler calls QueueUserAPC which will
* make it return.
*/
- data->interrupt_handle = mono_thread_info_prepare_interrupt (thread->handle);
+ data->interrupt_token = mono_thread_info_prepare_interrupt (info);
+
return MonoResumeThread;
}
}
MonoException *exc = mono_thread_request_interruption (can_raise_exception);
if (exc)
mono_raise_exception (exc);
- mono_thread_info_interrupt (thread->handle);
+
+ mono_thread_info_self_interrupt ();
+
return;
}
mono_thread_info_safe_suspend_and_run ((MonoNativeThreadId)(gsize)thread->tid, TRUE, abort_thread_critical, &data);
- if (data.interrupt_handle)
- mono_thread_info_finish_interrupt (data.interrupt_handle);
+ if (data.interrupt_token)
+ mono_thread_info_finish_interrupt (data.interrupt_token);
/*FIXME we need to wait for interruption to complete -- figure out how much into interruption we should wait for here*/
}
typedef struct{
MonoInternalThread *thread;
gboolean interrupt;
- gpointer interrupt_handle;
+ MonoThreadInfoInterruptToken *interrupt_token;
} SuspendThreadData;
static SuspendThreadResult
gboolean running_managed;
ji = mono_thread_info_get_last_managed (info);
- protected_wrapper = ji && !ji->async && mono_threads_is_critical_method (mono_jit_info_get_method (ji));
+ protected_wrapper = ji && !ji->is_trampoline && !ji->async && mono_threads_is_critical_method (mono_jit_info_get_method (ji));
running_managed = mono_jit_info_match (ji, MONO_CONTEXT_GET_IP (&mono_thread_info_get_suspend_state (info)->ctx));
if (running_managed && !protected_wrapper) {
if (InterlockedCompareExchange (&thread->interruption_requested, 1, 0) == 0)
InterlockedIncrement (&thread_interruption_requested);
if (data->interrupt)
- data->interrupt_handle = mono_thread_info_prepare_interrupt (thread->handle);
+ data->interrupt_token = mono_thread_info_prepare_interrupt (thread->thread_info);
if (mono_thread_notify_pending_exc_fn && !running_managed)
/* The JIT will notify the thread about the interruption */
data.interrupt = interrupt;
mono_thread_info_safe_suspend_and_run ((MonoNativeThreadId)(gsize)thread->tid, interrupt, suspend_thread_critical, &data);
- if (data.interrupt_handle)
- mono_thread_info_finish_interrupt (data.interrupt_handle);
+ if (data.interrupt_token)
+ mono_thread_info_finish_interrupt (data.interrupt_token);
UNLOCK_THREAD (thread);
}
}