#include <mono/metadata/metadata-internals.h>
#include <mono/metadata/marshal.h>
#include <mono/metadata/runtime.h>
+#include <mono/metadata/sgen-toggleref.h>
#include <mono/utils/atomic.h>
#include <mono/utils/mono-logger-internal.h>
#include <mono/utils/mono-memory-model.h>
#include <mono/utils/dtrace.h>
#include <mono/utils/gc_wrapper.h>
#include <mono/utils/mono-mutex.h>
+#include <mono/utils/mono-counters.h>
#if HAVE_BOEHM_GC
static void*
boehm_thread_register (MonoThreadInfo* info, void *baseptr);
+static void
+boehm_thread_unregister (MonoThreadInfo *p);
+static void
+register_test_toggleref_callback (void);
+
+#define BOEHM_GC_BIT_FINALIZER_AWARE 1
+static MonoGCFinalizerCallbacks fin_callbacks;
static void
mono_gc_warning (char *msg, GC_word arg)
{
MonoThreadInfoCallbacks cb;
const char *env;
+ int dummy;
if (gc_initialized)
return;
+ mono_counters_init ();
+
/*
* Handle the case when we are called from a thread different from the main thread,
* confusing libgc.
for (ptr = opts; *ptr; ++ptr) {
char *opt = *ptr;
if (g_str_has_prefix (opt, "max-heap-size=")) {
- glong max_heap;
+ size_t max_heap;
opt = strchr (opt, '=') + 1;
if (*opt && mono_gc_parse_environment_string_extract_number (opt, &max_heap)) {
exit (1);
}
continue;
+ } else if (g_str_has_prefix (opt, "toggleref-test")) {
+ register_test_toggleref_callback ();
+ continue;
} else {
/* Could be a parameter for sgen */
/*
memset (&cb, 0, sizeof (cb));
cb.thread_register = boehm_thread_register;
+ cb.thread_unregister = boehm_thread_unregister;
cb.mono_method_is_critical = (gpointer)mono_runtime_is_critical_method;
#ifndef HOST_WIN32
+ cb.thread_exit = mono_gc_pthread_exit;
cb.mono_gc_pthread_create = (gpointer)mono_gc_pthread_create;
#endif
mono_threads_init (&cb, sizeof (MonoThreadInfo));
mono_mutex_init (&mono_gc_lock);
+ mono_thread_info_attach (&dummy);
+
mono_gc_enable_events ();
gc_initialized = TRUE;
}
#endif
}
+static void
+boehm_thread_unregister (MonoThreadInfo *p)
+{
+ MonoNativeThreadId tid;
+
+ tid = mono_thread_info_get_tid (p);
+
+ if (p->runtime_thread)
+ mono_threads_add_joinable_thread ((gpointer)tid);
+}
+
gboolean
mono_object_is_alive (MonoObject* o)
{
mono_perfcounters->gc_gen0size = heap_size;
}
#endif
- gc_stats.major_gc_time_usecs += (mono_100ns_ticks () - gc_start_time) / 10;
+ gc_stats.major_gc_time += mono_100ns_ticks () - gc_start_time;
mono_trace_message (MONO_TRACE_GC, "gc took %d usecs", (mono_100ns_ticks () - gc_start_time) / 10);
break;
}
void
mono_gc_wbarrier_arrayref_copy (gpointer dest_ptr, gpointer src_ptr, int count)
{
- mono_gc_memmove (dest_ptr, src_ptr, count * sizeof (gpointer));
+ mono_gc_memmove_aligned (dest_ptr, src_ptr, count * sizeof (gpointer));
}
void
void
mono_gc_wbarrier_value_copy (gpointer dest, gpointer src, int count, MonoClass *klass)
{
- mono_gc_memmove (dest, src, count * mono_class_value_size (klass, NULL));
+ mono_gc_memmove_atomic (dest, src, count * mono_class_value_size (klass, NULL));
}
void
mono_gc_wbarrier_object_copy (MonoObject* obj, MonoObject *src)
{
/* do not copy the sync state */
- mono_gc_memmove ((char*)obj + sizeof (MonoObject), (char*)src + sizeof (MonoObject),
+ mono_gc_memmove_aligned ((char*)obj + sizeof (MonoObject), (char*)src + sizeof (MonoObject),
mono_object_class (obj)->instance_size - sizeof (MonoObject));
}
#endif
}
+int
+mono_gc_get_restart_signal (void)
+{
+#ifdef USE_INCLUDED_GC
+ return GC_get_restart_signal ();
+#else
+ return -1;
+#endif
+}
+
#if defined(USE_INCLUDED_LIBGC) && defined(USE_COMPILER_TLS) && defined(__linux__) && (defined(__i386__) || defined(__x86_64__))
extern __thread MONO_TLS_FAST void* GC_thread_tls;
#include "metadata-internals.h"
bytes_var = mono_mb_add_local (mb, &mono_defaults.int32_class->byval_arg);
if (atype == ATYPE_STRING) {
/* a string alloator method takes the args: (vtable, len) */
- /* bytes = (sizeof (MonoString) + ((len + 1) * 2)); */
+ /* bytes = (offsetof (MonoString, chars) + ((len + 1) * 2)); */
mono_mb_emit_ldarg (mb, 1);
mono_mb_emit_icon (mb, 1);
mono_mb_emit_byte (mb, MONO_CEE_ADD);
}
void *
-mono_gc_scan_object (void *obj)
+mono_gc_scan_object (void *obj, void *gc_data)
{
g_assert_not_reached ();
return NULL;
mono_gc_pthread_exit (void *retval)
{
pthread_exit (retval);
+ g_assert_not_reached ();
}
#endif
guint
mono_gc_get_vtable_bits (MonoClass *class)
{
+ if (fin_callbacks.is_class_finalization_aware) {
+ if (fin_callbacks.is_class_finalization_aware (class))
+ return BOEHM_GC_BIT_FINALIZER_AWARE;
+ }
return 0;
}
return G_MAXINT;
}
+void
+mono_gc_set_string_length (MonoString *str, gint32 new_length)
+{
+ mono_unichar2 *new_end = str->chars + new_length;
+
+ /* zero the discarded string. This null-delimits the string and allows
+ * the space to be reclaimed by SGen. */
+
+ memset (new_end, 0, (str->length - new_length + 1) * sizeof (mono_unichar2));
+ str->length = new_length;
+}
+
gboolean
mono_gc_user_markers_supported (void)
{
{
return flag;
}
+/* Toggleref support */
+
+void
+mono_gc_toggleref_add (MonoObject *object, mono_bool strong_ref)
+{
+ GC_toggleref_add ((GC_PTR)object, (int)strong_ref);
+}
+
+void
+mono_gc_toggleref_register_callback (MonoToggleRefStatus (*proccess_toggleref) (MonoObject *obj))
+{
+ GC_toggleref_register_callback ((int (*) (GC_PTR obj)) proccess_toggleref);
+}
+
+/* Test support code */
+
+static MonoToggleRefStatus
+test_toggleref_callback (MonoObject *obj)
+{
+ static MonoClassField *mono_toggleref_test_field;
+ int status = MONO_TOGGLE_REF_DROP;
+
+ if (!mono_toggleref_test_field) {
+ mono_toggleref_test_field = mono_class_get_field_from_name (mono_object_get_class (obj), "__test");
+ g_assert (mono_toggleref_test_field);
+ }
+
+ mono_field_get_value (obj, mono_toggleref_test_field, &status);
+ printf ("toggleref-cb obj %d\n", status);
+ return status;
+}
+
+static void
+register_test_toggleref_callback (void)
+{
+ mono_gc_toggleref_register_callback (test_toggleref_callback);
+}
+
+static gboolean
+is_finalization_aware (MonoObject *obj)
+{
+ MonoVTable *vt = obj->vtable;
+ return (vt->gc_bits & BOEHM_GC_BIT_FINALIZER_AWARE) == BOEHM_GC_BIT_FINALIZER_AWARE;
+}
+
+static void
+fin_notifier (MonoObject *obj)
+{
+ if (is_finalization_aware (obj))
+ fin_callbacks.object_queued_for_finalization (obj);
+}
+
+void
+mono_gc_register_finalizer_callbacks (MonoGCFinalizerCallbacks *callbacks)
+{
+ if (callbacks->version != MONO_GC_FINALIZER_EXTENSION_VERSION)
+ g_error ("Invalid finalizer callback version. Expected %d but got %d\n", MONO_GC_FINALIZER_EXTENSION_VERSION, callbacks->version);
+
+ fin_callbacks = *callbacks;
+
+ GC_set_finalizer_notify_proc ((void (*) (GC_PTR))fin_notifier);
+}
#endif /* no Boehm GC */