#include <mono/metadata/console-io.h>
#include <mono/utils/mono-semaphore.h>
#include <mono/utils/mono-memory-model.h>
+#include <mono/utils/mono-counters.h>
#ifndef HOST_WIN32
#include <pthread.h>
static HANDLE shutdown_event;
#endif
+GCStats gc_stats;
+
static void
add_thread_to_finalize (MonoInternalThread *thread)
{
return -1;
}
+static void*
+make_root_descr_all_refs (int numbits, gboolean pinned)
+{
+#ifdef HAVE_SGEN_GC
+ if (pinned)
+ return NULL;
+#endif
+ return mono_gc_make_root_descr_all_refs (numbits);
+}
+
static guint32
alloc_handle (HandleData *handles, MonoObject *obj, gboolean track)
{
if (!handles->size) {
handles->size = 32;
if (handles->type > HANDLE_WEAK_TRACK) {
- handles->entries = mono_gc_alloc_fixed (sizeof (gpointer) * handles->size, mono_gc_make_root_descr_all_refs (handles->size));
+ handles->entries = mono_gc_alloc_fixed (sizeof (gpointer) * handles->size, make_root_descr_all_refs (handles->size, handles->type == HANDLE_PINNED));
} else {
handles->entries = g_malloc0 (sizeof (gpointer) * handles->size);
handles->domain_ids = g_malloc0 (sizeof (guint16) * handles->size);
if (handles->type > HANDLE_WEAK_TRACK) {
gpointer *entries;
- entries = mono_gc_alloc_fixed (sizeof (gpointer) * new_size, mono_gc_make_root_descr_all_refs (new_size));
- memcpy (entries, handles->entries, sizeof (gpointer) * handles->size);
+ entries = mono_gc_alloc_fixed (sizeof (gpointer) * new_size, make_root_descr_all_refs (new_size, handles->type == HANDLE_PINNED));
+ mono_gc_memmove (entries, handles->entries, sizeof (gpointer) * handles->size);
mono_gc_free_fixed (handles->entries);
handles->entries = entries;
entries = g_malloc (sizeof (gpointer) * new_size);
/* we disable GC because we could lose some disappearing link updates */
mono_gc_disable ();
- memcpy (entries, handles->entries, sizeof (gpointer) * handles->size);
- memset (entries + handles->size, 0, sizeof (gpointer) * handles->size);
+ mono_gc_memmove (entries, handles->entries, sizeof (gpointer) * handles->size);
+ mono_gc_bzero (entries + handles->size, sizeof (gpointer) * handles->size);
memcpy (domain_ids, handles->domain_ids, sizeof (guint16) * handles->size);
for (i = 0; i < handles->size; ++i) {
MonoObject *obj = mono_gc_weak_link_get (&(handles->entries [i]));
mono_gc_weak_link_add (&(handles->entries [slot]), obj, track);
}
+#ifndef DISABLE_PERFCOUNTERS
mono_perfcounters->gc_num_handles++;
+#endif
unlock_handles (handles);
/*g_print ("allocated entry %d of type %d to object %p (in slot: %p)\n", slot, handles->type, obj, handles->entries [slot]);*/
res = (slot << 3) | (handles->type + 1);
} else {
/* print a warning? */
}
+#ifndef DISABLE_PERFCOUNTERS
mono_perfcounters->gc_num_handles--;
+#endif
/*g_print ("freed entry %d of type %d\n", slot, handles->type);*/
unlock_handles (handles);
mono_profiler_gc_handle (MONO_PROFILER_GC_HANDLE_DESTROYED, handles->type, gchandle, NULL);
return 0;
}
+#ifndef LAZY_GC_THREAD_CREATION
+static
+#endif
+void
+mono_gc_init_finalizer_thread (void)
+{
+ gc_thread = mono_thread_create_internal (mono_domain_get (), finalizer_thread, NULL, FALSE, 0);
+ ves_icall_System_Threading_Thread_SetName_internal (gc_thread, mono_string_new (mono_domain_get (), "Finalizer"));
+}
+
void
mono_gc_init (void)
{
MONO_GC_REGISTER_ROOT_FIXED (gc_handles [HANDLE_NORMAL].entries);
MONO_GC_REGISTER_ROOT_FIXED (gc_handles [HANDLE_PINNED].entries);
+ 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_TIME_INTERVAL, &gc_stats.minor_gc_time_usecs);
+ mono_counters_register ("Major GC time", MONO_COUNTER_GC | MONO_COUNTER_TIME_INTERVAL, &gc_stats.major_gc_time_usecs);
+
mono_gc_base_init ();
if (mono_gc_is_disabled ()) {
MONO_SEM_INIT (&finalizer_sem, 0);
#endif
- gc_thread = mono_thread_create_internal (mono_domain_get (), finalizer_thread, NULL, FALSE, 0);
- ves_icall_System_Threading_Thread_SetName_internal (gc_thread, mono_string_new (mono_domain_get (), "Finalizer"));
+#ifndef LAZY_GC_THREAD_CREATION
+ mono_gc_init_finalizer_thread ();
+#endif
}
void
return FALSE;
if (is_suffix) {
+ gulong unshifted;
+
+ if (val < 0) /* negative numbers cannot be suffixed */
+ return FALSE;
if (*(endptr + 1)) /* Invalid string. */
return FALSE;
+
+ unshifted = (gulong)val;
val <<= shift;
+ if (val < 0) /* overflow */
+ return FALSE;
+ if (((gulong)val >> shift) != unshifted) /* value too large */
+ return FALSE;
}
*out = val;