if test x$buildsgen = xyes; then
AC_DEFINE(HAVE_MOVING_COLLECTOR, 1, [Moving collector])
SGEN_DEFINES="-DHAVE_SGEN_GC"
- if test "x$gc_msg" = "x"; then
- gc_msg="sgen"
- else
- gc_msg="sgen and $gc_msg"
- fi
+ conc_gc_msg=""
if test x$with_sgen_default_concurrent != xno; then
AC_DEFINE(HAVE_CONC_GC_AS_DEFAULT, 1, [Defaults to concurrent GC])
+ conc_gc_msg=" (concurrent by default)"
+ fi
+
+ if test "x$gc_msg" = "x"; then
+ gc_msg="sgen$conc_gc_msg"
+ else
+ gc_msg="sgen$conc_gc_msg and $gc_msg"
fi
fi
AC_SUBST(SGEN_DEFINES)
sgen_stop_world (0);
if (sgen_concurrent_collection_in_progress ())
- sgen_perform_collection (0, GENERATION_OLD, "clear domain", TRUE);
+ sgen_perform_collection (0, GENERATION_OLD, "clear domain", TRUE, FALSE);
SGEN_ASSERT (0, !sgen_concurrent_collection_in_progress (), "We just ordered a synchronous collection. Why are we collecting concurrently?");
major_collector.finish_sweeping ();
char*
mono_gc_get_description (void)
{
+#ifdef HAVE_CONC_GC_AS_DEFAULT
+ return g_strdup ("sgen (concurrent by default)");
+#else
return g_strdup ("sgen");
+#endif
}
void
sgen_ensure_free_space (size, GENERATION_OLD);
} else {
if (sgen_need_major_collection (size))
- sgen_perform_collection (size, GENERATION_OLD, "mature allocation failure", !for_mature);
+ sgen_perform_collection (size, GENERATION_OLD, "mature allocation failure", !for_mature, TRUE);
}
if (collect_before_allocs) {
if (((current_alloc % collect_before_allocs) == 0) && nursery_section) {
- sgen_perform_collection (0, GENERATION_NURSERY, "collect-before-alloc-triggered", TRUE);
+ sgen_perform_collection (0, GENERATION_NURSERY, "collect-before-alloc-triggered", TRUE, TRUE);
if (!degraded_mode && sgen_can_alloc_size (size) && real_size <= SGEN_MAX_SMALL_OBJ_SIZE) {
// FIXME:
g_assert_not_reached ();
if (collect_before_allocs) {
if (((current_alloc % collect_before_allocs) == 0) && nursery_section) {
LOCK_GC;
- sgen_perform_collection (0, GENERATION_NURSERY, "collect-before-alloc-triggered", TRUE);
+ sgen_perform_collection (0, GENERATION_NURSERY, "collect-before-alloc-triggered", TRUE, TRUE);
UNLOCK_GC;
}
}
if (generation_to_collect == -1)
return;
- sgen_perform_collection (size, generation_to_collect, reason, FALSE);
+ sgen_perform_collection (size, generation_to_collect, reason, FALSE, TRUE);
}
/*
* LOCKING: Assumes the GC lock is held.
*/
void
-sgen_perform_collection (size_t requested_size, int generation_to_collect, const char *reason, gboolean wait_to_finish)
+sgen_perform_collection (size_t requested_size, int generation_to_collect, const char *reason, gboolean wait_to_finish, gboolean stw)
{
TV_DECLARE (gc_total_start);
TV_DECLARE (gc_total_end);
SGEN_ASSERT (0, generation_to_collect == GENERATION_NURSERY || generation_to_collect == GENERATION_OLD, "What generation is this?");
- sgen_stop_world (generation_to_collect);
+ if (stw)
+ sgen_stop_world (generation_to_collect);
+ else
+ SGEN_ASSERT (0, sgen_is_world_stopped (), "We can only collect if the world is stopped");
+
TV_GETTIME (gc_total_start);
TV_GETTIME (gc_total_end);
time_max = MAX (time_max, TV_ELAPSED (gc_total_start, gc_total_end));
- sgen_restart_world (oldest_generation_collected);
+ if (stw)
+ sgen_restart_world (oldest_generation_collected);
}
/*
LOCK_GC;
if (generation > 1)
generation = 1;
- sgen_perform_collection (0, generation, "user request", TRUE);
+ sgen_perform_collection (0, generation, "user request", TRUE, TRUE);
UNLOCK_GC;
}
void sgen_ensure_free_space (size_t size, int generation);
void sgen_gc_collect (int generation);
-void sgen_perform_collection (size_t requested_size, int generation_to_collect, const char *reason, gboolean wait_to_finish);
+void sgen_perform_collection (size_t requested_size, int generation_to_collect, const char *reason, gboolean wait_to_finish, gboolean stw);
int sgen_gc_collection_count (int generation);
/* FIXME: what exactly does this return? */
*as pinned alloc is requested by the runtime.
*/
if (!res) {
- sgen_perform_collection (0, GENERATION_OLD, "pinned alloc failure", TRUE);
+ sgen_perform_collection (0, GENERATION_OLD, "pinned alloc failure", TRUE, TRUE);
res = alloc_obj (vtable, size, TRUE, has_references);
}
return (GCObject *)res;
#include <sys/sysctl.h>
#include <sys/types.h>
#else
+#if defined (HAVE_SYS_UTSNAME_H)
+#include <sys/utsname.h>
+#endif
#include <stdio.h>
#endif
* hit this path if the target doesn't have sys/auxv.h.
*/
+#if defined (HAVE_SYS_UTSNAME_H)
+ struct utsname name;
+
+ /* Only fails if `name` is invalid (it isn't). */
+ g_assert (!uname (&name));
+
+ if (!strncmp (name.machine, "aarch64", 7) || !strncmp (name.machine, "armv8", 5)) {
+ /*
+ * We're a 32-bit program running on an ARMv8 system.
+ * Whether the system is actually 32-bit or 64-bit
+ * doesn't matter to us. The important thing is that
+ * all 3 of ARMv8's execution states (A64, A32, T32)
+ * are guaranteed to have all of the features that
+ * we want to detect and use.
+ *
+ * We do this ARMv8 detection via uname () because
+ * in the early days of ARMv8 on Linux, the
+ * /proc/cpuinfo format was a disaster and there
+ * were multiple (merged into mainline) attempts at
+ * cleaning it up (read: breaking applications that
+ * tried to rely on it). So now multiple ARMv8
+ * systems in the wild have different /proc/cpuinfo
+ * output, some of which are downright useless.
+ *
+ * So, when it comes to detecting ARMv8 in a 32-bit
+ * program, it's better to just avoid /proc/cpuinfo
+ * entirely. Maybe in a decade or two, we won't
+ * have to worry about this mess that the Linux ARM
+ * maintainers created. One can hope.
+ */
+
+ mono_hwcap_arm_is_v5 = TRUE;
+ mono_hwcap_arm_is_v6 = TRUE;
+ mono_hwcap_arm_is_v7 = TRUE;
+
+ mono_hwcap_arm_has_vfp = TRUE;
+ mono_hwcap_arm_has_vfp3 = TRUE;
+ mono_hwcap_arm_has_vfp3_d16 = TRUE;
+
+ mono_hwcap_arm_has_thumb = TRUE;
+ mono_hwcap_arm_has_thumb2 = TRUE;
+ }
+#endif
+
char buf [512];
char *line;