X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fmonitor.c;h=1e05eaddc43c7d9cdc9c7deda8bdf252ae36ba02;hb=c28164a651e968a5f4704db98d26e3d9e3f522aa;hp=a7b5556d9e64e6db96b0912cf5d4a0b8424f4045;hpb=669beaed8380fa592533c8755f72593b4422d01d;p=mono.git diff --git a/mono/metadata/monitor.c b/mono/metadata/monitor.c index a7b5556d9e6..1e05eaddc43 100644 --- a/mono/metadata/monitor.c +++ b/mono/metadata/monitor.c @@ -58,7 +58,7 @@ struct _MonoThreadsSync #ifdef HAVE_MOVING_COLLECTOR gint32 hash_code; #endif - volatile guint32 entry_count; + volatile gint32 entry_count; HANDLE entry_sem; GSList *wait_list; void *data; @@ -91,6 +91,63 @@ mono_monitor_cleanup (void) /*DeleteCriticalSection (&monitor_mutex);*/ } +static int +monitor_is_on_freelist (MonoThreadsSync *mon) +{ + MonitorArray *marray; + for (marray = monitor_allocated; marray; marray = marray->next) { + if (mon >= marray->monitors && mon < &marray->monitors [marray->num_monitors]) + return TRUE; + } + return FALSE; +} + +/** + * mono_locks_dump: + * @include_untaken: + * + * Print a report on stdout of the managed locks currently held by + * threads. If @include_untaken is specified, list also inflated locks + * which are unheld. + * This is supposed to be used in debuggers like gdb. + */ +void +mono_locks_dump (gboolean include_untaken) +{ + int i; + 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) + on_freelist++; + for (marray = monitor_allocated; marray; marray = marray->next) { + total += marray->num_monitors; + num_arrays++; + for (i = 0; i < marray->num_monitors; ++i) { + mon = &marray->monitors [i]; + if (mon->data == NULL) { + if (i < marray->num_monitors - 1) + to_recycle++; + } else { + if (!monitor_is_on_freelist (mon->data)) { + MonoObject *holder = mono_gc_weak_link_get (&mon->data); + if (mon->owner) { + g_print ("Lock %p in object %p held by thread %p, nest level: %d\n", + mon, holder, (void*)mon->owner, mon->nest); + if (mon->entry_sem) + g_print ("\tWaiting on semaphore %p: %d\n", mon->entry_sem, mon->entry_count); + } else if (include_untaken) { + g_print ("Lock %p in object %p untaken\n", mon, holder); + } + used++; + } + } + } + } + g_print ("Total locks (in %d array(s)): %d, used: %d, on freelist: %d, to recycle: %d\n", + num_arrays, total, used, on_freelist, to_recycle); +} + /* LOCKING: this is called with monitor_mutex held */ static void mon_finalize (MonoThreadsSync *mon) @@ -404,6 +461,7 @@ retry: if (mon->entry_sem == NULL) { /* Create the semaphore */ sem = CreateSemaphore (NULL, 0, 0x7fffffff, NULL); + g_assert (sem != NULL); if (InterlockedCompareExchangePointer ((gpointer*)&mon->entry_sem, sem, NULL) != NULL) { /* Someone else just put a handle here */ CloseHandle (sem); @@ -755,6 +813,9 @@ ves_icall_System_Threading_Monitor_Monitor_wait (MonoObject *obj, guint32 ms) mono_raise_exception (mono_get_exception_synchronization_lock ("Not locked by this thread")); return FALSE; } + + /* Do this WaitSleepJoin check before creating the event handle */ + mono_thread_current_check_pending_interrupt (); event = CreateEvent (NULL, FALSE, FALSE, NULL); if (event == NULL) {