static gboolean finalizing_root_domain = FALSE;
+gboolean log_finalizers = FALSE;
+gboolean do_not_finalize = FALSE;
+
#define mono_finalizer_lock() mono_mutex_lock (&finalizer_mutex)
#define mono_finalizer_unlock() mono_mutex_unlock (&finalizer_mutex)
static mono_mutex_t finalizer_mutex;
GCStats gc_stats;
+static guint32
+guarded_wait (HANDLE handle, guint32 timeout, gboolean alertable)
+{
+ guint32 result;
+
+ MONO_PREPARE_BLOCKING
+ result = WaitForSingleObjectEx (handle, timeout, alertable);
+ MONO_FINISH_BLOCKING
+
+ return result;
+}
+
static void
add_thread_to_finalize (MonoInternalThread *thread)
{
void
mono_gc_run_finalize (void *obj, void *data)
{
+ if (do_not_finalize)
+ return;
+
MonoObject *exc = NULL;
MonoObject *o;
#ifndef HAVE_SGEN_GC
o = (MonoObject*)((char*)obj + GPOINTER_TO_UINT (data));
+ if (log_finalizers)
+ g_log ("mono-gc-finalizers", G_LOG_LEVEL_DEBUG, "<%s at %p> Starting finalizer checks.", o->vtable->klass->name, o);
+
if (suspend_finalizers)
return;
/* make sure the finalizer is not called again if the object is resurrected */
object_register_finalizer (obj, NULL);
+ if (log_finalizers)
+ g_log ("mono-gc-finalizers", G_LOG_LEVEL_MESSAGE, "<%s at %p> Registered finalizer as processed.", o->vtable->klass->name, o);
+
if (o->vtable->klass == mono_defaults.internal_thread_class) {
MonoInternalThread *t = (MonoInternalThread*)o;
* create and precompile a wrapper which calls the finalize method using
* a CALLVIRT.
*/
+ if (log_finalizers)
+ g_log ("mono-gc-finalizers", G_LOG_LEVEL_MESSAGE, "<%s at %p> Compiling finalizer.", o->vtable->klass->name, o);
+
if (!domain->finalize_runtime_invoke) {
MonoMethod *invoke = mono_marshal_get_runtime_invoke (mono_class_get_method_from_name_flags (mono_defaults.object_class, "Finalize", 0, 0), TRUE);
o->vtable->klass->name_space, o->vtable->klass->name);
}
+ if (log_finalizers)
+ g_log ("mono-gc-finalizers", G_LOG_LEVEL_MESSAGE, "<%s at %p> Calling finalizer.", o->vtable->klass->name, o);
+
runtime_invoke (o, NULL, &exc, NULL);
+ if (log_finalizers)
+ g_log ("mono-gc-finalizers", G_LOG_LEVEL_MESSAGE, "<%s at %p> Returned from finalizer.", o->vtable->klass->name, o);
+
if (exc)
mono_internal_thread_unhandled_exception (exc);
timeout = INFINITE;
while (TRUE) {
- res = WaitForSingleObjectEx (done_event, timeout, TRUE);
+ res = guarded_wait (done_event, timeout, TRUE);
/* printf ("WAIT RES: %d.\n", res); */
if (res == WAIT_IO_COMPLETION) {
gint64
ves_icall_System_GC_GetTotalMemory (MonoBoolean forceCollection)
{
- MONO_ARCH_SAVE_REGS;
-
if (forceCollection)
mono_gc_collect (mono_gc_max_generation ());
return mono_gc_get_used_size ();
void
ves_icall_System_GC_KeepAlive (MonoObject *obj)
{
- MONO_ARCH_SAVE_REGS;
-
/*
* Does nothing.
*/
void
ves_icall_System_GC_ReRegisterForFinalize (MonoObject *obj)
{
- if (!obj)
- mono_raise_exception (mono_get_exception_argument_null ("obj"));
+ MONO_CHECK_ARG_NULL (obj,);
object_register_finalizer (obj, mono_gc_run_finalize);
}
void
ves_icall_System_GC_SuppressFinalize (MonoObject *obj)
{
- if (!obj)
- mono_raise_exception (mono_get_exception_argument_null ("obj"));
+ MONO_CHECK_ARG_NULL (obj,);
/* delegates have no finalizers, but we register them to deal with the
* unmanaged->managed trampoline. We don't let the user suppress it
ResetEvent (pending_done_event);
mono_gc_finalize_notify ();
/* g_print ("Waiting for pending finalizers....\n"); */
- WaitForSingleObjectEx (pending_done_event, INFINITE, TRUE);
+ guarded_wait (pending_done_event, INFINITE, TRUE);
/* g_print ("Done pending....\n"); */
#endif
}
ves_icall_System_GC_register_ephemeron_array (MonoObject *array)
{
#ifdef HAVE_SGEN_GC
- if (!mono_gc_ephemeron_array_add (array))
- mono_raise_exception (mono_object_domain (array)->out_of_memory_ex);
+ if (!mono_gc_ephemeron_array_add (array)) {
+ mono_set_pending_exception (mono_object_domain (array)->out_of_memory_ex);
+ return;
+ }
#endif
}
guint slot = gchandle >> 3;
guint type = (gchandle & 7) - 1;
HandleData *handles = &gc_handles [type];
- MonoObject *old_obj = NULL;
if (type > 3)
return;
lock_handles (handles);
if (slot < handles->size && (handles->bitmap [slot / 32] & (1 << (slot % 32)))) {
if (handles->type <= HANDLE_WEAK_TRACK) {
- old_obj = handles->entries [slot];
if (handles->entries [slot])
mono_gc_weak_link_remove (&handles->entries [slot], handles->type == HANDLE_WEAK_TRACK);
if (obj)
*/
g_assert (mono_domain_get () == mono_get_root_domain ());
+ mono_gc_set_skip_thread (TRUE);
+ MONO_PREPARE_BLOCKING
if (wait) {
/* An alertable wait is required so this thread can be suspended on windows */
#endif
}
wait = TRUE;
+ MONO_FINISH_BLOCKING
+ mono_gc_set_skip_thread (FALSE);
mono_threads_perform_thread_dump ();
MONO_GC_REGISTER_ROOT_FIXED (gc_handles [HANDLE_NORMAL].entries);
MONO_GC_REGISTER_ROOT_FIXED (gc_handles [HANDLE_PINNED].entries);
- mono_counters_register ("Created object count", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &mono_stats.new_object_count);
- mono_counters_register ("Minor GC collections", MONO_COUNTER_GC | MONO_COUNTER_INT, &gc_stats.minor_gc_count);
- mono_counters_register ("Major GC collections", MONO_COUNTER_GC | MONO_COUNTER_INT, &gc_stats.major_gc_count);
- mono_counters_register ("Minor GC time", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &gc_stats.minor_gc_time);
- mono_counters_register ("Major GC time", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &gc_stats.major_gc_time);
- mono_counters_register ("Major GC time concurrent", MONO_COUNTER_GC | MONO_COUNTER_LONG | MONO_COUNTER_TIME, &gc_stats.major_gc_time_concurrent);
+ mono_counters_register ("Minor GC collections", MONO_COUNTER_GC | MONO_COUNTER_UINT, &gc_stats.minor_gc_count);
+ mono_counters_register ("Major GC collections", MONO_COUNTER_GC | MONO_COUNTER_UINT, &gc_stats.major_gc_count);
+ mono_counters_register ("Minor GC time", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &gc_stats.minor_gc_time);
+ mono_counters_register ("Major GC time", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &gc_stats.major_gc_time);
+ mono_counters_register ("Major GC time concurrent", MONO_COUNTER_GC | MONO_COUNTER_ULONG | MONO_COUNTER_TIME, &gc_stats.major_gc_time_concurrent);
mono_gc_base_init ();
mono_gc_finalize_notify ();
/* Finishing the finalizer thread, so wait a little bit... */
/* MS seems to wait for about 2 seconds */
- if (WaitForSingleObjectEx (shutdown_event, 2000, FALSE) == WAIT_TIMEOUT) {
+ if (guarded_wait (shutdown_event, 2000, FALSE) == WAIT_TIMEOUT) {
int ret;
/* Set a flag which the finalizer thread can check */
mono_thread_internal_stop (gc_thread);
/* Wait for it to stop */
- ret = WaitForSingleObjectEx (gc_thread->handle, 100, TRUE);
+ ret = guarded_wait (gc_thread->handle, 100, TRUE);
if (ret == WAIT_TIMEOUT) {
/*
int ret;
/* Wait for the thread to actually exit */
- ret = WaitForSingleObjectEx (gc_thread->handle, INFINITE, TRUE);
+ ret = guarded_wait (gc_thread->handle, INFINITE, TRUE);
g_assert (ret == WAIT_OBJECT_0);
- mono_thread_join ((gpointer)gc_thread->tid);
+ mono_thread_join (GUINT_TO_POINTER (gc_thread->tid));
}
}
gc_thread = NULL;