static __thread gsize tls_pthread_self MONO_TLS_FAST;
#endif
-#ifndef PLATFORM_WIN32
+#ifndef HOST_WIN32
#ifdef HAVE_KW_THREAD
#define GetCurrentThreadId() tls_pthread_self
#else
void
mono_monitor_cleanup (void)
{
+ MonoThreadsSync *mon;
+ /* MonitorArray *marray, *next = NULL; */
+
/*DeleteCriticalSection (&monitor_mutex);*/
+
+ /* The monitors on the freelist don't have weak links - mark them */
+ for (mon = monitor_freelist; mon; mon = mon->data)
+ mon->wait_list = (gpointer)-1;
+
+ /* FIXME: This still crashes with sgen (async_read.exe) */
+ /*
+ for (marray = monitor_allocated; marray; marray = next) {
+ int i;
+
+ for (i = 0; i < marray->num_monitors; ++i) {
+ mon = &marray->monitors [i];
+ if (mon->wait_list != (gpointer)-1)
+ mono_gc_weak_link_remove (&mon->data);
+ }
+
+ next = marray->next;
+ g_free (marray);
+ }
+ */
}
/*
void
mono_monitor_init_tls (void)
{
-#if !defined(PLATFORM_WIN32) && defined(HAVE_KW_THREAD)
+#if !defined(HOST_WIN32) && defined(HAVE_KW_THREAD)
tls_pthread_self = pthread_self ();
#endif
}
static void
mon_finalize (MonoThreadsSync *mon)
{
- LOCK_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": Finalizing sync %p", mon));
+ LOCK_DEBUG (g_message ("%s: Finalizing sync %p", __func__, mon));
if (mon->entry_sem != NULL) {
CloseHandle (mon->entry_sem);
mon->data = monitor_freelist;
monitor_freelist = mon;
+#ifndef DISABLE_PERFCOUNTERS
mono_perfcounters->gc_sync_blocks--;
+#endif
}
/* LOCKING: this is called with monitor_mutex held */
for (i = 0; i < marray->num_monitors; ++i) {
if (marray->monitors [i].data == NULL) {
new = &marray->monitors [i];
+ if (new->wait_list) {
+ /* Orphaned events left by aborted threads */
+ while (new->wait_list) {
+ LOCK_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": (%d): Closing orphaned event %d", GetCurrentThreadId (), new->wait_list->data));
+ CloseHandle (new->wait_list->data);
+ new->wait_list = g_slist_remove (new->wait_list, new->wait_list->data);
+ }
+ }
+ mono_gc_weak_link_remove (&new->data);
new->data = monitor_freelist;
monitor_freelist = new;
}
/* need to allocate a new array of monitors */
if (!monitor_freelist) {
MonitorArray *last;
- LOCK_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": allocating more monitors: %d", array_size));
+ LOCK_DEBUG (g_message ("%s: allocating more monitors: %d", __func__, array_size));
marray = g_malloc0 (sizeof (MonoArray) + array_size * sizeof (MonoThreadsSync));
marray->num_monitors = array_size;
array_size *= 2;
new->owner = id;
new->nest = 1;
+#ifndef DISABLE_PERFCOUNTERS
mono_perfcounters->gc_sync_blocks++;
+#endif
return new;
}
guint32 then = 0, now, delta;
guint32 waitms;
guint32 ret;
- MonoThread *thread;
+ MonoInternalThread *thread;
- LOCK_DEBUG (g_message(G_GNUC_PRETTY_FUNCTION
- ": (%d) Trying to lock object %p (%d ms)", id, obj, ms));
+ LOCK_DEBUG (g_message("%s: (%d) Trying to lock object %p (%d ms)", __func__, id, obj, ms));
if (G_UNLIKELY (!obj)) {
mono_raise_exception (mono_get_exception_argument_null ("obj"));
}
/* The object must be locked by someone else... */
+#ifndef DISABLE_PERFCOUNTERS
mono_perfcounters->thread_contentions++;
+#endif
/* If ms is 0 we don't block, but just fail straight away */
if (ms == 0) {
- LOCK_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": (%d) timed out, returning FALSE", id));
+ LOCK_DEBUG (g_message ("%s: (%d) timed out, returning FALSE", __func__, id));
return 0;
}
InterlockedIncrement (&mon->entry_count);
+#ifndef DISABLE_PERFCOUNTERS
mono_perfcounters->thread_queue_len++;
mono_perfcounters->thread_queue_max++;
- thread = mono_thread_current ();
+#endif
+ thread = mono_thread_internal_current ();
mono_thread_set_state (thread, ThreadState_WaitSleepJoin);
mono_thread_clr_state (thread, ThreadState_WaitSleepJoin);
InterlockedDecrement (&mon->entry_count);
+#ifndef DISABLE_PERFCOUNTERS
mono_perfcounters->thread_queue_len--;
+#endif
if (ms != INFINITE) {
now = mono_msec_ticks ();
if (now < then) {
/* The counter must have wrapped around */
- LOCK_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION
- ": wrapped around! now=0x%x then=0x%x", now, then));
+ LOCK_DEBUG (g_message ("%s: wrapped around! now=0x%x then=0x%x", __func__, now, then));
now += (0xffffffff - then);
then = 0;
- LOCK_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": wrap rejig: now=0x%x then=0x%x delta=0x%x", now, then, now-then));
+ LOCK_DEBUG (g_message ("%s: wrap rejig: now=0x%x then=0x%x delta=0x%x", __func__, now, then, now-then));
}
delta = now - then;
}
} else {
if (ret == WAIT_TIMEOUT || (ret == WAIT_IO_COMPLETION && !allow_interruption)) {
- if (ret == WAIT_IO_COMPLETION && (mono_thread_test_state (mono_thread_current (), (ThreadState_StopRequested|ThreadState_SuspendRequested)))) {
+ if (ret == WAIT_IO_COMPLETION && (mono_thread_test_state (mono_thread_internal_current (), (ThreadState_StopRequested|ThreadState_SuspendRequested)))) {
/*
* We have to obey a stop/suspend request even if
* allow_interruption is FALSE to avoid hangs at shutdown.
}
/* We must have timed out */
- LOCK_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": (%d) timed out waiting, returning FALSE", id));
+ LOCK_DEBUG (g_message ("%s: (%d) timed out waiting, returning FALSE", __func__, id));
mono_profiler_monitor_event (obj, MONO_PROFILER_MONITOR_FAIL);
MonoThreadsSync *mon;
guint32 nest;
- LOCK_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": (%d) Unlocking %p", GetCurrentThreadId (), obj));
+ LOCK_DEBUG (g_message ("%s: (%d) Unlocking %p", __func__, GetCurrentThreadId (), obj));
if (G_UNLIKELY (!obj)) {
mono_raise_exception (mono_get_exception_argument_null ("obj"));
nest = mon->nest - 1;
if (nest == 0) {
- LOCK_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION
- ": (%d) Object %p is now unlocked", GetCurrentThreadId (), obj));
+ LOCK_DEBUG (g_message ("%s: (%d) Object %p is now unlocked", __func__, GetCurrentThreadId (), obj));
/* object is now unlocked, leave nest==1 so we don't
* need to set it when the lock is reacquired
ReleaseSemaphore (mon->entry_sem, 1, NULL);
}
} else {
- LOCK_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION
- ": (%d) Object %p is now locked %d times", GetCurrentThreadId (), obj, nest));
+ LOCK_DEBUG (g_message ("%s: (%d) Object %p is now locked %d times", __func__, GetCurrentThreadId (), obj, nest));
mon->nest = nest;
}
}
}
static void
-emit_obj_syncp_check (MonoMethodBuilder *mb, int syncp_loc, int *obj_null_branch, int *syncp_true_false_branch,
- gboolean branch_on_true)
+emit_obj_syncp_check (MonoMethodBuilder *mb, int syncp_loc, int *obj_null_branch, int *true_locktaken_branch, int *syncp_true_false_branch,
+ int *thin_hash_branch, gboolean branch_on_true)
{
/*
ldarg 0 obj
mono_mb_emit_byte (mb, CEE_LDARG_0);
*obj_null_branch = mono_mb_emit_short_branch (mb, CEE_BRFALSE_S);
+ /*
+ ldarg.1
+ ldind.i1
+ brtrue.s true_locktaken
+ */
+ if (true_locktaken_branch) {
+ mono_mb_emit_byte (mb, CEE_LDARG_1);
+ mono_mb_emit_byte (mb, CEE_LDIND_I1);
+ *true_locktaken_branch = mono_mb_emit_short_branch (mb, CEE_BRTRUE_S);
+ }
+
/*
ldarg 0 obj
conv.i objp
mono_mb_emit_byte (mb, CEE_ADD);
mono_mb_emit_byte (mb, CEE_LDIND_I);
mono_mb_emit_stloc (mb, syncp_loc);
+
+
+ if (mono_gc_is_moving ()) {
+ /*check for a thin hash*/
+ mono_mb_emit_ldloc (mb, syncp_loc);
+ mono_mb_emit_icon (mb, 0x01);
+ mono_mb_emit_byte (mb, CEE_CONV_I);
+ mono_mb_emit_byte (mb, CEE_AND);
+ *thin_hash_branch = mono_mb_emit_short_branch (mb, CEE_BRTRUE_S);
+
+ /*clear gc bits*/
+ mono_mb_emit_ldloc (mb, syncp_loc);
+ mono_mb_emit_icon (mb, ~0x3);
+ mono_mb_emit_byte (mb, CEE_CONV_I);
+ mono_mb_emit_byte (mb, CEE_AND);
+ mono_mb_emit_stloc (mb, syncp_loc);
+ } else {
+ *thin_hash_branch = 0;
+ }
+
mono_mb_emit_ldloc (mb, syncp_loc);
*syncp_true_false_branch = mono_mb_emit_short_branch (mb, branch_on_true ? CEE_BRTRUE_S : CEE_BRFALSE_S);
}
+static MonoMethod* monitor_il_fastpaths[3];
+
+gboolean
+mono_monitor_is_il_fastpath_wrapper (MonoMethod *method)
+{
+ int i;
+ for (i = 0; i < 3; ++i) {
+ if (monitor_il_fastpaths [i] == method)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+enum {
+ FASTPATH_ENTER,
+ FASTPATH_ENTERV4,
+ FASTPATH_EXIT
+};
+
+
+static MonoMethod*
+register_fastpath (MonoMethod *method, int idx)
+{
+ mono_memory_barrier ();
+ monitor_il_fastpaths [idx] = method;
+ return method;
+}
+
static MonoMethod*
mono_monitor_get_fast_enter_method (MonoMethod *monitor_enter_method)
{
- static MonoMethod *fast_monitor_enter;
- static MonoMethod *compare_exchange_method;
-
MonoMethodBuilder *mb;
- int obj_null_branch, syncp_null_branch, has_owner_branch, other_owner_branch, tid_branch;
+ MonoMethod *res;
+ static MonoMethod *compare_exchange_method;
+ int obj_null_branch, true_locktaken_branch = 0, syncp_null_branch, has_owner_branch, other_owner_branch, tid_branch, thin_hash_branch;
int tid_loc, syncp_loc, owner_loc;
int thread_tls_offset;
+ gboolean is_v4 = mono_method_signature (monitor_enter_method)->param_count == 2;
+ int fast_path_idx = is_v4 ? FASTPATH_ENTERV4 : FASTPATH_ENTER;
+ WrapperInfo *info;
-#ifdef HAVE_MOVING_COLLECTOR
- return NULL;
-#endif
+ /* The !is_v4 version is not used/tested */
+ g_assert (is_v4);
thread_tls_offset = mono_thread_get_tls_offset ();
if (thread_tls_offset == -1)
return NULL;
- if (fast_monitor_enter)
- return fast_monitor_enter;
+ if (monitor_il_fastpaths [fast_path_idx])
+ return monitor_il_fastpaths [fast_path_idx];
if (!compare_exchange_method) {
MonoMethodDesc *desc;
return NULL;
}
- mb = mono_mb_new (mono_defaults.monitor_class, "FastMonitorEnter", MONO_WRAPPER_UNKNOWN);
+ mb = mono_mb_new (mono_defaults.monitor_class, is_v4 ? "FastMonitorEnterV4" : "FastMonitorEnter", MONO_WRAPPER_UNKNOWN);
mb->method->slot = -1;
mb->method->flags = METHOD_ATTRIBUTE_PUBLIC | METHOD_ATTRIBUTE_STATIC |
syncp_loc = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
owner_loc = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
- emit_obj_syncp_check (mb, syncp_loc, &obj_null_branch, &syncp_null_branch, FALSE);
+ emit_obj_syncp_check (mb, syncp_loc, &obj_null_branch, is_v4 ? &true_locktaken_branch : NULL, &syncp_null_branch, &thin_hash_branch, FALSE);
/*
mono. tls thread_tls_offset threadp
mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
mono_mb_emit_byte (mb, CEE_MONO_TLS);
mono_mb_emit_i4 (mb, thread_tls_offset);
- mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoThread, tid));
+ mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoInternalThread, tid));
mono_mb_emit_byte (mb, CEE_ADD);
mono_mb_emit_byte (mb, CEE_LDIND_I);
mono_mb_emit_stloc (mb, tid_loc);
mono_mb_emit_byte (mb, CEE_LDC_I4_0);
mono_mb_emit_managed_call (mb, compare_exchange_method, NULL);
has_owner_branch = mono_mb_emit_short_branch (mb, CEE_BRTRUE_S);
+
+ if (is_v4) {
+ mono_mb_emit_byte (mb, CEE_LDARG_1);
+ mono_mb_emit_byte (mb, CEE_LDC_I4_1);
+ mono_mb_emit_byte (mb, CEE_STIND_I1);
+ }
mono_mb_emit_byte (mb, CEE_RET);
/*
mono_mb_emit_byte (mb, CEE_LDC_I4_1);
mono_mb_emit_byte (mb, CEE_ADD);
mono_mb_emit_byte (mb, CEE_STIND_I4);
+
+ if (is_v4) {
+ mono_mb_emit_byte (mb, CEE_LDARG_1);
+ mono_mb_emit_byte (mb, CEE_LDC_I4_1);
+ mono_mb_emit_byte (mb, CEE_STIND_I1);
+ }
+
mono_mb_emit_byte (mb, CEE_RET);
/*
ret
*/
+ if (thin_hash_branch)
+ mono_mb_patch_short_branch (mb, thin_hash_branch);
mono_mb_patch_short_branch (mb, obj_null_branch);
mono_mb_patch_short_branch (mb, syncp_null_branch);
mono_mb_patch_short_branch (mb, has_owner_branch);
mono_mb_patch_short_branch (mb, other_owner_branch);
+ if (true_locktaken_branch)
+ mono_mb_patch_short_branch (mb, true_locktaken_branch);
mono_mb_emit_byte (mb, CEE_LDARG_0);
+ if (is_v4)
+ mono_mb_emit_byte (mb, CEE_LDARG_1);
mono_mb_emit_managed_call (mb, monitor_enter_method, NULL);
mono_mb_emit_byte (mb, CEE_RET);
- fast_monitor_enter = mono_mb_create_method (mb, mono_signature_no_pinvoke (monitor_enter_method), 5);
- mono_mb_free (mb);
+ res = register_fastpath (mono_mb_create_method (mb, mono_signature_no_pinvoke (monitor_enter_method), 5), fast_path_idx);
+
+ info = mono_image_alloc0 (mono_defaults.corlib, sizeof (WrapperInfo));
+ info->subtype = is_v4 ? WRAPPER_SUBTYPE_FAST_MONITOR_ENTER_V4 : WRAPPER_SUBTYPE_FAST_MONITOR_ENTER;
+ mono_marshal_set_wrapper_info (res, info);
- return fast_monitor_enter;
+ mono_mb_free (mb);
+ return res;
}
static MonoMethod*
mono_monitor_get_fast_exit_method (MonoMethod *monitor_exit_method)
{
- static MonoMethod *fast_monitor_exit;
-
MonoMethodBuilder *mb;
- int obj_null_branch, has_waiting_branch, has_syncp_branch, owned_branch, nested_branch;
+ MonoMethod *res;
+ int obj_null_branch, has_waiting_branch, has_syncp_branch, owned_branch, nested_branch, thin_hash_branch;
int thread_tls_offset;
int syncp_loc;
-
-#ifdef HAVE_MOVING_COLLECTOR
- return NULL;
-#endif
+ WrapperInfo *info;
thread_tls_offset = mono_thread_get_tls_offset ();
if (thread_tls_offset == -1)
return NULL;
- if (fast_monitor_exit)
- return fast_monitor_exit;
+ if (monitor_il_fastpaths [FASTPATH_EXIT])
+ return monitor_il_fastpaths [FASTPATH_EXIT];
mb = mono_mb_new (mono_defaults.monitor_class, "FastMonitorExit", MONO_WRAPPER_UNKNOWN);
syncp_loc = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
- emit_obj_syncp_check (mb, syncp_loc, &obj_null_branch, &has_syncp_branch, TRUE);
+ emit_obj_syncp_check (mb, syncp_loc, &obj_null_branch, NULL, &has_syncp_branch, &thin_hash_branch, TRUE);
/*
ret
mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
mono_mb_emit_byte (mb, CEE_MONO_TLS);
mono_mb_emit_i4 (mb, thread_tls_offset);
- mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoThread, tid));
+ mono_mb_emit_icon (mb, G_STRUCT_OFFSET (MonoInternalThread, tid));
mono_mb_emit_byte (mb, CEE_ADD);
mono_mb_emit_byte (mb, CEE_LDIND_I);
owned_branch = mono_mb_emit_short_branch (mb, CEE_BEQ_S);
ret
*/
+ if (thin_hash_branch)
+ mono_mb_patch_short_branch (mb, thin_hash_branch);
mono_mb_patch_short_branch (mb, obj_null_branch);
mono_mb_patch_short_branch (mb, has_waiting_branch);
mono_mb_emit_byte (mb, CEE_LDARG_0);
mono_mb_emit_managed_call (mb, monitor_exit_method, NULL);
mono_mb_emit_byte (mb, CEE_RET);
- fast_monitor_exit = mono_mb_create_method (mb, mono_signature_no_pinvoke (monitor_exit_method), 5);
+ res = register_fastpath (mono_mb_create_method (mb, mono_signature_no_pinvoke (monitor_exit_method), 5), FASTPATH_EXIT);
mono_mb_free (mb);
- return fast_monitor_exit;
+ info = mono_image_alloc0 (mono_defaults.corlib, sizeof (WrapperInfo));
+ info->subtype = WRAPPER_SUBTYPE_FAST_MONITOR_EXIT;
+ mono_marshal_set_wrapper_info (res, info);
+
+ return res;
}
MonoMethod*
return res == 1;
}
+void
+ves_icall_System_Threading_Monitor_Monitor_try_enter_with_atomic_var (MonoObject *obj, guint32 ms, char *lockTaken)
+{
+ gint32 res;
+ do {
+ res = mono_monitor_try_enter_internal (obj, ms, TRUE);
+ /*This means we got interrupted during the wait and didn't got the monitor.*/
+ if (res == -1)
+ mono_thread_interruption_checkpoint ();
+ } while (res == -1);
+ /*It's safe to do it from here since interruption would happen only on the wrapper.*/
+ *lockTaken = res == 1;
+}
+
gboolean
ves_icall_System_Threading_Monitor_Monitor_test_owner (MonoObject *obj)
{
MonoThreadsSync *mon;
- LOCK_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION
- ": Testing if %p is owned by thread %d", obj, GetCurrentThreadId()));
+ LOCK_DEBUG (g_message ("%s: Testing if %p is owned by thread %d", __func__, obj, GetCurrentThreadId()));
mon = obj->synchronisation;
#ifdef HAVE_MOVING_COLLECTOR
{
MonoThreadsSync *mon;
- LOCK_DEBUG (g_message(G_GNUC_PRETTY_FUNCTION
- ": (%d) Testing if %p is owned by any thread", GetCurrentThreadId (), obj));
+ LOCK_DEBUG (g_message("%s: (%d) Testing if %p is owned by any thread", __func__, GetCurrentThreadId (), obj));
mon = obj->synchronisation;
#ifdef HAVE_MOVING_COLLECTOR
{
MonoThreadsSync *mon;
- LOCK_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": (%d) Pulsing %p",
- GetCurrentThreadId (), obj));
+ LOCK_DEBUG (g_message ("%s: (%d) Pulsing %p", __func__, GetCurrentThreadId (), obj));
mon = obj->synchronisation;
#ifdef HAVE_MOVING_COLLECTOR
return;
}
- LOCK_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": (%d) %d threads waiting",
- GetCurrentThreadId (), g_slist_length (mon->wait_list)));
+ LOCK_DEBUG (g_message ("%s: (%d) %d threads waiting", __func__, GetCurrentThreadId (), g_slist_length (mon->wait_list)));
if (mon->wait_list != NULL) {
- LOCK_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION
- ": (%d) signalling and dequeuing handle %p",
- GetCurrentThreadId (), mon->wait_list->data));
+ LOCK_DEBUG (g_message ("%s: (%d) signalling and dequeuing handle %p", __func__, GetCurrentThreadId (), mon->wait_list->data));
SetEvent (mon->wait_list->data);
mon->wait_list = g_slist_remove (mon->wait_list, mon->wait_list->data);
{
MonoThreadsSync *mon;
- LOCK_DEBUG (g_message(G_GNUC_PRETTY_FUNCTION ": (%d) Pulsing all %p",
- GetCurrentThreadId (), obj));
+ LOCK_DEBUG (g_message("%s: (%d) Pulsing all %p", __func__, GetCurrentThreadId (), obj));
mon = obj->synchronisation;
#ifdef HAVE_MOVING_COLLECTOR
return;
}
- LOCK_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": (%d) %d threads waiting",
- GetCurrentThreadId (), g_slist_length (mon->wait_list)));
+ LOCK_DEBUG (g_message ("%s: (%d) %d threads waiting", __func__, GetCurrentThreadId (), g_slist_length (mon->wait_list)));
while (mon->wait_list != NULL) {
- LOCK_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION
- ": (%d) signalling and dequeuing handle %p",
- GetCurrentThreadId (), mon->wait_list->data));
+ LOCK_DEBUG (g_message ("%s: (%d) signalling and dequeuing handle %p", __func__, GetCurrentThreadId (), mon->wait_list->data));
SetEvent (mon->wait_list->data);
mon->wait_list = g_slist_remove (mon->wait_list, mon->wait_list->data);
guint32 ret;
gboolean success = FALSE;
gint32 regain;
- MonoThread *thread = mono_thread_current ();
+ MonoInternalThread *thread = mono_thread_internal_current ();
- LOCK_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION
- ": (%d) Trying to wait for %p with timeout %dms",
- GetCurrentThreadId (), obj, ms));
+ LOCK_DEBUG (g_message ("%s: (%d) Trying to wait for %p with timeout %dms", __func__, GetCurrentThreadId (), obj, ms));
mon = obj->synchronisation;
#ifdef HAVE_MOVING_COLLECTOR
return FALSE;
}
- LOCK_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": (%d) queuing handle %p",
- GetCurrentThreadId (), event));
+ LOCK_DEBUG (g_message ("%s: (%d) queuing handle %p", __func__, GetCurrentThreadId (), event));
mono_thread_current_check_pending_interrupt ();
mon->nest = 1;
mono_monitor_exit (obj);
- LOCK_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": (%d) Unlocked %p lock %p",
- GetCurrentThreadId (), obj, mon));
+ LOCK_DEBUG (g_message ("%s: (%d) Unlocked %p lock %p", __func__, GetCurrentThreadId (), obj, mon));
/* There's no race between unlocking mon and waiting for the
* event, because auto reset events are sticky, and this event
mono_thread_clr_state (thread, ThreadState_WaitSleepJoin);
if (mono_thread_interruption_requested ()) {
- CloseHandle (event);
+ /*
+ * Can't remove the event from wait_list, since the monitor is not locked by
+ * us. So leave it there, mon_new () will delete it when the mon structure
+ * is placed on the free list.
+ * FIXME: The caller expects to hold the lock after the wait returns, but it
+ * doesn't happen in this case:
+ * http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=97268
+ */
return FALSE;
}
mon->nest = nest;
- LOCK_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": (%d) Regained %p lock %p",
- GetCurrentThreadId (), obj, mon));
+ LOCK_DEBUG (g_message ("%s: (%d) Regained %p lock %p", __func__, GetCurrentThreadId (), obj, mon));
if (ret == WAIT_TIMEOUT) {
/* Poll the event again, just in case it was signalled
*/
if (ret == WAIT_OBJECT_0) {
- LOCK_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": (%d) Success",
- GetCurrentThreadId ()));
+ LOCK_DEBUG (g_message ("%s: (%d) Success", __func__, GetCurrentThreadId ()));
success = TRUE;
} else {
- LOCK_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": (%d) Wait failed, dequeuing handle %p",
- GetCurrentThreadId (), event));
+ LOCK_DEBUG (g_message ("%s: (%d) Wait failed, dequeuing handle %p", __func__, GetCurrentThreadId (), event));
/* No pulse, so we have to remove ourself from the
* wait queue
*/