#include <mono/io-layer/io-layer.h>
#include <mono/metadata/object-internals.h>
#include <mono/metadata/class-internals.h>
-#include <mono/metadata/gc-internal.h>
+#include <mono/metadata/gc-internals.h>
#include <mono/metadata/method-builder.h>
#include <mono/metadata/debug-helpers.h>
#include <mono/metadata/tabledefs.h>
MonoThreadsSync monitors [MONO_ZERO_LEN_ARRAY];
};
-#define mono_monitor_allocator_lock() mono_mutex_lock (&monitor_mutex)
-#define mono_monitor_allocator_unlock() mono_mutex_unlock (&monitor_mutex)
+#define mono_monitor_allocator_lock() mono_os_mutex_lock (&monitor_mutex)
+#define mono_monitor_allocator_unlock() mono_os_mutex_unlock (&monitor_mutex)
static mono_mutex_t monitor_mutex;
static MonoThreadsSync *monitor_freelist;
static MonitorArray *monitor_allocated;
void
mono_monitor_init (void)
{
- mono_mutex_init_recursive (&monitor_mutex);
+ mono_os_mutex_init_recursive (&monitor_mutex);
}
void
MonoThreadsSync *mon;
/* MonitorArray *marray, *next = NULL; */
- /*mono_mutex_destroy (&monitor_mutex);*/
+ /*mono_os_mutex_destroy (&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;
+ for (mon = monitor_freelist; mon; mon = (MonoThreadsSync *)mon->data)
+ mon->wait_list = (GSList *)-1;
/*
* FIXME: This still crashes with sgen (async_read.exe)
int used = 0, on_freelist = 0, to_recycle = 0, total = 0, num_arrays = 0;
MonoThreadsSync *mon;
MonitorArray *marray;
- for (mon = monitor_freelist; mon; mon = mon->data)
+ for (mon = monitor_freelist; mon; mon = (MonoThreadsSync *)mon->data)
on_freelist++;
for (marray = monitor_allocated; marray; marray = marray->next) {
total += marray->num_monitors;
if (i < marray->num_monitors - 1)
to_recycle++;
} else {
- if (!monitor_is_on_freelist (mon->data)) {
+ if (!monitor_is_on_freelist ((MonoThreadsSync *)mon->data)) {
MonoObject *holder = (MonoObject *)mono_gchandle_get_target ((guint32)mon->data);
if (mon_status_get_owner (mon->status)) {
g_print ("Lock %p in object %p held by thread %d, nest level: %d\n",
static MonoThreadsSync *
mon_new (gsize id)
{
- MonoThreadsSync *new;
+ MonoThreadsSync *new_;
if (!monitor_freelist) {
MonitorArray *marray;
int i;
/* see if any sync block has been collected */
- new = NULL;
+ new_ = NULL;
for (marray = monitor_allocated; marray; marray = marray->next) {
for (i = 0; i < marray->num_monitors; ++i) {
if (mono_gchandle_get_target ((guint32)marray->monitors [i].data) == NULL) {
- new = &marray->monitors [i];
- if (new->wait_list) {
+ 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", mono_thread_info_get_small_id (), new->wait_list->data));
- CloseHandle (new->wait_list->data);
- new->wait_list = g_slist_remove (new->wait_list, new->wait_list->data);
+ while (new_->wait_list) {
+ LOCK_DEBUG (g_message (G_GNUC_PRETTY_FUNCTION ": (%d): Closing orphaned event %d", mono_thread_info_get_small_id (), new_->wait_list->data));
+ CloseHandle (new_->wait_list->data);
+ new_->wait_list = g_slist_remove (new_->wait_list, new_->wait_list->data);
}
}
- mono_gchandle_free ((guint32)new->data);
- new->data = monitor_freelist;
- monitor_freelist = new;
+ mono_gchandle_free ((guint32)new_->data);
+ new_->data = monitor_freelist;
+ monitor_freelist = new_;
}
}
/* small perf tweak to avoid scanning all the blocks */
- if (new)
+ if (new_)
break;
}
/* need to allocate a new array of monitors */
if (!monitor_freelist) {
MonitorArray *last;
LOCK_DEBUG (g_message ("%s: allocating more monitors: %d", __func__, array_size));
- marray = g_malloc0 (sizeof (MonoArray) + array_size * sizeof (MonoThreadsSync));
+ marray = (MonitorArray *)g_malloc0 (MONO_SIZEOF_MONO_ARRAY + array_size * sizeof (MonoThreadsSync));
marray->num_monitors = array_size;
array_size *= 2;
/* link into the freelist */
}
}
- new = monitor_freelist;
- monitor_freelist = new->data;
+ new_ = monitor_freelist;
+ monitor_freelist = (MonoThreadsSync *)new_->data;
- new->status = mon_status_set_owner (0, id);
- new->status = mon_status_init_entry_count (new->status);
- new->nest = 1;
- new->data = NULL;
+ new_->status = mon_status_set_owner (0, id);
+ new_->status = mon_status_init_entry_count (new_->status);
+ new_->nest = 1;
+ new_->data = NULL;
#ifndef DISABLE_PERFCOUNTERS
mono_perfcounters->gc_sync_blocks++;
#endif
- return new;
+ return new_;
}
static MonoThreadsSync*
nlw = lock_word_new_inflated (mon);
mono_memory_write_barrier ();
- tmp_lw.sync = InterlockedCompareExchangePointer ((gpointer*)&obj->synchronisation, nlw.sync, old_lw.sync);
+ tmp_lw.sync = (MonoThreadsSync *)InterlockedCompareExchangePointer ((gpointer*)&obj->synchronisation, nlw.sync, old_lw.sync);
if (tmp_lw.sync != old_lw.sync) {
/* Someone else inflated the lock in the meantime */
discard_mon (mon);
mon->nest = lock_word_get_nest (old_lw);
}
mono_memory_write_barrier ();
- tmp_lw.sync = InterlockedCompareExchangePointer ((gpointer*)&obj->synchronisation, nlw.sync, old_lw.sync);
+ tmp_lw.sync = (MonoThreadsSync *)InterlockedCompareExchangePointer ((gpointer*)&obj->synchronisation, nlw.sync, old_lw.sync);
if (tmp_lw.sync == old_lw.sync) {
/* Successfully inflated the lock */
return;
LockWord old_lw;
lw = lock_word_new_thin_hash (hash);
- old_lw.sync = InterlockedCompareExchangePointer ((gpointer*)&obj->synchronisation, lw.sync, NULL);
+ old_lw.sync = (MonoThreadsSync *)InterlockedCompareExchangePointer ((gpointer*)&obj->synchronisation, lw.sync, NULL);
if (old_lw.sync == NULL) {
return hash;
}
else
new_lw.lock_word = 0;
- tmp_lw.sync = InterlockedCompareExchangePointer ((gpointer*)&obj->synchronisation, new_lw.sync, old_lw.sync);
+ tmp_lw.sync = (MonoThreadsSync *)InterlockedCompareExchangePointer ((gpointer*)&obj->synchronisation, new_lw.sync, old_lw.sync);
if (old_lw.sync != tmp_lw.sync) {
/* Someone inflated the lock in the meantime */
mono_monitor_exit_inflated (obj);
* We have to obey a stop/suspend request even if
* allow_interruption is FALSE to avoid hangs at shutdown.
*/
- if (!mono_thread_test_state (mono_thread_internal_current (), (ThreadState_StopRequested|ThreadState_SuspendRequested))) {
+ if (!mono_thread_test_state (mono_thread_internal_current (), (MonoThreadState)(ThreadState_StopRequested | ThreadState_SuspendRequested | ThreadState_AbortRequested))) {
if (ms != INFINITE) {
now = mono_msec_ticks ();
if (now < then) {
} else {
LockWord nlw, old_lw;
nlw = lock_word_increment_nest (lw);
- old_lw.sync = InterlockedCompareExchangePointer ((gpointer*)&obj->synchronisation, nlw.sync, lw.sync);
+ old_lw.sync = (MonoThreadsSync *)InterlockedCompareExchangePointer ((gpointer*)&obj->synchronisation, nlw.sync, lw.sync);
if (old_lw.sync != lw.sync) {
/* Someone else inflated it in the meantime */
g_assert (lock_word_is_inflated (old_lw));
}
gboolean
+mono_monitor_enter_fast (MonoObject *obj)
+{
+ return mono_monitor_try_enter_internal (obj, 0, FALSE) == 1;
+}
+
+gboolean
mono_monitor_try_enter (MonoObject *obj, guint32 ms)
{
return mono_monitor_try_enter_internal (obj, ms, FALSE) == 1;
do {
res = mono_monitor_try_enter_internal (obj, ms, TRUE);
- if (res == -1)
- mono_thread_interruption_checkpoint ();
+ if (res == -1) {
+ MonoException *exc = mono_thread_interruption_checkpoint ();
+ if (exc) {
+ mono_set_pending_exception (exc);
+ return FALSE;
+ }
+ }
} while (res == -1);
return res == 1;
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 ();
+ if (res == -1) {
+ MonoException *exc = mono_thread_interruption_checkpoint ();
+ if (exc) {
+ mono_set_pending_exception (exc);
+ return;
+ }
+ }
} while (res == -1);
/*It's safe to do it from here since interruption would happen only on the wrapper.*/
*lockTaken = res == 1;
void
mono_monitor_enter_v4 (MonoObject *obj, char *lock_taken)
{
-
if (*lock_taken == 1) {
mono_set_pending_exception (mono_get_exception_argument ("lockTaken", "lockTaken is already true"));
return;
ves_icall_System_Threading_Monitor_Monitor_try_enter_with_atomic_var (obj, INFINITE, lock_taken);
}
+/*
+ * mono_monitor_enter_v4_fast:
+ *
+ * Same as mono_monitor_enter_v4, but return immediately if the
+ * monitor cannot be acquired.
+ * Returns TRUE if the lock was acquired, FALSE otherwise.
+ */
+gboolean
+mono_monitor_enter_v4_fast (MonoObject *obj, char *lock_taken)
+{
+ if (*lock_taken == 1)
+ return FALSE;
+ gint32 res = mono_monitor_try_enter_internal (obj, 0, TRUE);
+ *lock_taken = res == 1;
+ return res == 1;
+}
+
gboolean
ves_icall_System_Threading_Monitor_Monitor_test_owner (MonoObject *obj)
{
* about the monitor error checking
*/
mono_thread_clr_state (thread, ThreadState_WaitSleepJoin);
-
- if (mono_thread_interruption_requested ()) {
- /*
- * 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;
- }
/* Regain the lock with the previous nest count */
do {
regain = mono_monitor_try_enter_inflated (obj, INFINITE, TRUE, id);
- if (regain == -1)
- mono_thread_interruption_checkpoint ();
+ /* We must regain the lock before handling interruption requests */
} while (regain == -1);
- if (regain == 0) {
- /* Something went wrong, so throw a
- * SynchronizationLockException
- */
- CloseHandle (event);
- mono_set_pending_exception (mono_get_exception_synchronization_lock ("Failed to regain lock"));
- return FALSE;
- }
+ g_assert (regain == 1);
mon->nest = nest;