X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fgc.c;h=53cce47edadcfc59778f208bb9c529734edc77fc;hb=a713a14521da8ddf992c4a3e64855d56cb7897a3;hp=350d439bee3e05e6e64e6afd62b9f5a12f5c5578;hpb=c69ede50f2ab8deaee1b9970e025c0365a6496d6;p=mono.git diff --git a/mono/metadata/gc.c b/mono/metadata/gc.c index 350d439bee3..53cce47edad 100644 --- a/mono/metadata/gc.c +++ b/mono/metadata/gc.c @@ -91,13 +91,13 @@ static void mono_reference_queue_cleanup (void); static void reference_queue_clear_for_domain (MonoDomain *domain); -static guint32 -guarded_wait (HANDLE handle, guint32 timeout, gboolean alertable) +static MonoThreadInfoWaitRet +guarded_wait (MonoThreadHandle *thread_handle, guint32 timeout, gboolean alertable) { - guint32 result; + MonoThreadInfoWaitRet result; MONO_ENTER_GC_SAFE; - result = WaitForSingleObjectEx (handle, timeout, alertable); + result = mono_thread_info_wait_one_handle (thread_handle, timeout, alertable); MONO_EXIT_GC_SAFE; return result; @@ -116,6 +116,8 @@ break_coop_alertable_wait (gpointer user_data) mono_coop_mutex_lock (ud->mutex); mono_coop_cond_signal (ud->cond); mono_coop_mutex_unlock (ud->mutex); + + g_free (ud); } /* @@ -127,23 +129,30 @@ break_coop_alertable_wait (gpointer user_data) static inline gint coop_cond_timedwait_alertable (MonoCoopCond *cond, MonoCoopMutex *mutex, guint32 timeout_ms, gboolean *alertable) { + BreakCoopAlertableWaitUD *ud; int res; if (alertable) { - BreakCoopAlertableWaitUD ud; + ud = g_new0 (BreakCoopAlertableWaitUD, 1); + ud->cond = cond; + ud->mutex = mutex; - *alertable = FALSE; - ud.cond = cond; - ud.mutex = mutex; - mono_thread_info_install_interrupt (break_coop_alertable_wait, &ud, alertable); - if (*alertable) + mono_thread_info_install_interrupt (break_coop_alertable_wait, ud, alertable); + if (*alertable) { + g_free (ud); return 0; + } } res = mono_coop_cond_timedwait (cond, mutex, timeout_ms); if (alertable) { mono_thread_info_uninstall_interrupt (alertable); if (*alertable) return 0; + else { + /* the interrupt token has not been taken by another + * thread, so it's our responsability to free it up. */ + g_free (ud); + } } return res; } @@ -317,8 +326,12 @@ mono_gc_run_finalize (void *obj, void *data) if (log_finalizers) g_log ("mono-gc-finalizers", G_LOG_LEVEL_MESSAGE, "<%s at %p> Calling finalizer.", o->vtable->klass->name, o); + mono_profiler_gc_finalize_object_begin (o); + runtime_invoke (o, NULL, &exc, NULL); + mono_profiler_gc_finalize_object_end (o); + if (log_finalizers) g_log ("mono-gc-finalizers", G_LOG_LEVEL_MESSAGE, "<%s at %p> Returned from finalizer.", o->vtable->klass->name, o); @@ -481,14 +494,14 @@ mono_domain_finalize (MonoDomain *domain, guint32 timeout) mono_gc_finalize_notify (); if (timeout == -1) - timeout = INFINITE; - if (timeout != INFINITE) + timeout = MONO_INFINITE_WAIT; + if (timeout != MONO_INFINITE_WAIT) start = mono_msec_ticks (); ret = TRUE; for (;;) { - if (timeout == INFINITE) { + if (timeout == MONO_INFINITE_WAIT) { res = mono_coop_sem_wait (&req->done, MONO_SEM_FLAGS_ALERTABLE); } else { gint64 elapsed = mono_msec_ticks () - start; @@ -547,8 +560,6 @@ mono_domain_finalize (MonoDomain *domain, guint32 timeout) mono_gc_finalize_threadpool_threads (); } - mono_profiler_appdomain_event (domain, MONO_PROFILE_END_UNLOAD); - done: if (InterlockedDecrement (&req->ref) == 0) { mono_coop_sem_destroy (&req->done); @@ -631,7 +642,9 @@ ves_icall_System_GC_WaitForPendingFinalizers (void) ResetEvent (pending_done_event); mono_gc_finalize_notify (); /* g_print ("Waiting for pending finalizers....\n"); */ - guarded_wait (pending_done_event, INFINITE, TRUE); + MONO_ENTER_GC_SAFE; + WaitForSingleObjectEx (pending_done_event, INFINITE, TRUE); + MONO_EXIT_GC_SAFE; /* g_print ("Done pending....\n"); */ #else gboolean alerted = FALSE; @@ -639,7 +652,7 @@ ves_icall_System_GC_WaitForPendingFinalizers (void) pending_done = FALSE; mono_gc_finalize_notify (); while (!pending_done) { - coop_cond_timedwait_alertable (&pending_done_cond, &pending_done_mutex, INFINITE, &alerted); + coop_cond_timedwait_alertable (&pending_done_cond, &pending_done_mutex, MONO_INFINITE_WAIT, &alerted); if (alerted) break; } @@ -719,7 +732,7 @@ ves_icall_System_GCHandle_GetAddrOfPinnedObject (guint32 handle) } else { /* the C# code will check and throw the exception */ /* FIXME: missing !klass->blittable test, see bug #61134 */ - if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_AUTO_LAYOUT) + if (mono_class_is_auto_layout (klass)) return (gpointer)-1; return (char*)obj + sizeof (MonoObject); } @@ -905,11 +918,15 @@ finalizer_thread (gpointer unused) finalize_domain_objects (); + mono_profiler_gc_finalize_begin (); + /* If finished == TRUE, mono_gc_cleanup has been called (from mono_runtime_cleanup), * before the domain is unloaded. */ mono_gc_invoke_finalizers (); + mono_profiler_gc_finalize_end (); + mono_threads_join_threads (); reference_queue_proccess_all (); @@ -999,6 +1016,7 @@ mono_gc_cleanup (void) if (!gc_disabled) { finished = TRUE; if (mono_thread_internal_current () != gc_thread) { + int ret; gint64 start_ticks = mono_msec_ticks (); gint64 end_ticks = start_ticks + 2000; @@ -1020,8 +1038,6 @@ mono_gc_cleanup (void) } if (!finalizer_thread_exited) { - int ret; - /* Set a flag which the finalizer thread can check */ suspend_finalizers = TRUE; mono_gc_suspend_finalizers (); @@ -1032,23 +1048,22 @@ mono_gc_cleanup (void) /* Wait for it to stop */ ret = guarded_wait (gc_thread->handle, 100, TRUE); - if (ret == WAIT_TIMEOUT) { + if (ret == MONO_THREAD_INFO_WAIT_RET_TIMEOUT) { /* * The finalizer thread refused to exit. Make it stop. */ mono_thread_internal_stop (gc_thread); ret = guarded_wait (gc_thread->handle, 100, TRUE); - g_assert (ret != WAIT_TIMEOUT); + g_assert (ret != MONO_THREAD_INFO_WAIT_RET_TIMEOUT); /* The thread can't set this flag */ finalizer_thread_exited = TRUE; } } - int ret; /* Wait for the thread to actually exit */ - ret = guarded_wait (gc_thread->handle, INFINITE, TRUE); - g_assert (ret == WAIT_OBJECT_0); + ret = guarded_wait (gc_thread->handle, MONO_INFINITE_WAIT, TRUE); + g_assert (ret == MONO_THREAD_INFO_WAIT_RET_SUCCESS_0); mono_thread_join (GUINT_TO_POINTER (gc_thread->tid)); g_assert (finalizer_thread_exited);