#include <mono/utils/mono-threads.h>
#include <mono/utils/dtrace.h>
#include <mono/utils/gc_wrapper.h>
-#include <mono/utils/mono-mutex.h>
+#include <mono/utils/mono-os-mutex.h>
#include <mono/utils/mono-counters.h>
#if HAVE_BOEHM_GC
/* GC Handles */
static mono_mutex_t handle_section;
-#define lock_handles(handles) mono_mutex_lock (&handle_section)
-#define unlock_handles(handles) mono_mutex_unlock (&handle_section)
+#define lock_handles(handles) mono_os_mutex_lock (&handle_section)
+#define unlock_handles(handles) mono_os_mutex_unlock (&handle_section)
typedef struct {
guint32 *bitmap;
GC_finalizer_notifier = mono_gc_finalize_notify;
GC_init_gcj_malloc (5, NULL);
+ GC_allow_register_threads ();
if ((env = g_getenv ("MONO_GC_PARAMS"))) {
char **ptr, **opts = g_strsplit (env, ",", -1);
cb.mono_method_is_critical = (gpointer)mono_runtime_is_critical_method;
mono_threads_init (&cb, sizeof (MonoThreadInfo));
- mono_mutex_init (&mono_gc_lock);
- mono_mutex_init_recursive (&handle_section);
+ mono_os_mutex_init (&mono_gc_lock);
+ mono_os_mutex_init_recursive (&handle_section);
mono_thread_info_attach (&dummy);
return GC_thread_is_registered ();
}
-extern int GC_thread_register_foreign (void *base_addr);
-
gboolean
mono_gc_register_thread (void *baseptr)
{
static void*
boehm_thread_register (MonoThreadInfo* info, void *baseptr)
{
- if (mono_gc_is_gc_thread())
- return info;
-#if !defined(HOST_WIN32)
- return GC_thread_register_foreign (baseptr) ? info : NULL;
-#else
- return NULL;
-#endif
+ struct GC_stack_base sb;
+ int res;
+
+ /* TODO: use GC_get_stack_base instead of baseptr. */
+ sb.mem_base = baseptr;
+ res = GC_register_my_thread (&sb);
+ if (res == GC_UNIMPLEMENTED)
+ return NULL; /* Cannot happen with GC v7+. */
+ return info;
}
static void
static gint64 gc_start_time;
static void
-on_gc_notification (GCEventType event)
+on_gc_notification (GC_EventType event)
{
MonoGCEvent e = (MonoGCEvent)event;
void
mono_gc_enable_events (void)
{
- GC_notify_event = on_gc_notification;
+ GC_set_on_collection_event (on_gc_notification);
GC_on_heap_resize = on_gc_heap_resize;
}
int
mono_gc_get_restart_signal (void)
{
- return GC_get_restart_signal ();
+ return GC_get_thr_restart_signal ();
}
#if defined(USE_COMPILER_TLS) && defined(__linux__) && (defined(__i386__) || defined(__x86_64__))
mono_mb_emit_byte (mb, 0x0D); /* CEE_MONO_TLS */
mono_mb_emit_i4 (mb, tls_key);
if (atype == ATYPE_FREEPTR || atype == ATYPE_FREEPTR_FOR_BOX || atype == ATYPE_STRING)
- mono_mb_emit_icon (mb, G_STRUCT_OFFSET (struct GC_Thread_Rep, ptrfree_freelists));
+ mono_mb_emit_icon (mb, G_STRUCT_OFFSET (struct GC_Thread_Rep, tlfs)
+ + G_STRUCT_OFFSET (struct thread_local_freelists,
+ ptrfree_freelists));
else if (atype == ATYPE_NORMAL)
- mono_mb_emit_icon (mb, G_STRUCT_OFFSET (struct GC_Thread_Rep, normal_freelists));
+ mono_mb_emit_icon (mb, G_STRUCT_OFFSET (struct GC_Thread_Rep, tlfs)
+ + G_STRUCT_OFFSET (struct thread_local_freelists,
+ normal_freelists));
else if (atype == ATYPE_GCJ)
- mono_mb_emit_icon (mb, G_STRUCT_OFFSET (struct GC_Thread_Rep, gcj_freelists));
+ mono_mb_emit_icon (mb, G_STRUCT_OFFSET (struct GC_Thread_Rep, tlfs)
+ + G_STRUCT_OFFSET (struct thread_local_freelists,
+ gcj_freelists));
else
g_assert_not_reached ();
mono_mb_emit_byte (mb, MONO_CEE_ADD);
return res;
res = create_allocator (atype, TLS_KEY_BOEHM_GC_THREAD, slowpath);
- mono_mutex_lock (&mono_gc_lock);
+ mono_os_mutex_lock (&mono_gc_lock);
if (cache [atype]) {
mono_free_method (res);
res = cache [atype];
mono_memory_barrier ();
cache [atype] = res;
}
- mono_mutex_unlock (&mono_gc_lock);
+ mono_os_mutex_unlock (&mono_gc_lock);
return res;
}
return NULL;
}
- gboolean
- mono_gc_set_allow_synchronous_major (gboolean flag)
- {
- return flag;
- }
/* Toggleref support */
void
mono_gc_toggleref_add (MonoObject *object, mono_bool strong_ref)
{
- GC_toggleref_add ((GC_PTR)object, (int)strong_ref);
+ if (GC_toggleref_add ((GC_PTR)object, (int)strong_ref) != GC_SUCCESS)
+ g_error ("GC_toggleref_add failed\n");
}
void
mono_gc_toggleref_register_callback (MonoToggleRefStatus (*proccess_toggleref) (MonoObject *obj))
{
- GC_toggleref_register_callback ((int (*) (GC_PTR obj)) proccess_toggleref);
+ GC_set_toggleref_func ((GC_ToggleRefStatus (*) (GC_PTR obj)) proccess_toggleref);
}
/* Test support code */
fin_callbacks = *callbacks;
- GC_set_finalizer_notify_proc ((void (*) (GC_PTR))fin_notifier);
+ GC_set_await_finalize_proc ((void (*) (GC_PTR))fin_notifier);
}
#define BITMAP_SIZE (sizeof (*((HandleData *)NULL)->bitmap) * CHAR_BIT)
#include <mono/sgen/gc-internal-agnostic.h>
#include <mono/utils/gc_wrapper.h>
-#define mono_domain_finalizers_lock(domain) mono_mutex_lock (&(domain)->finalizable_objects_hash_lock);
-#define mono_domain_finalizers_unlock(domain) mono_mutex_unlock (&(domain)->finalizable_objects_hash_lock);
+#define mono_domain_finalizers_lock(domain) mono_os_mutex_lock (&(domain)->finalizable_objects_hash_lock);
+#define mono_domain_finalizers_unlock(domain) mono_os_mutex_unlock (&(domain)->finalizable_objects_hash_lock);
/* Register a memory area as a conservatively scanned GC root */
#define MONO_GC_REGISTER_ROOT_PINNING(x,src,msg) mono_gc_register_root ((char*)&(x), sizeof(x), MONO_GC_DESCRIPTOR_NULL, (src), (msg))
void ves_icall_System_GC_register_ephemeron_array (MonoObject *array);
MonoObject *ves_icall_System_GC_get_ephemeron_tombstone (void);
- MonoBoolean ves_icall_Mono_Runtime_SetGCAllowSynchronousMajor (MonoBoolean flag);
extern void mono_gc_init (void);
extern void mono_gc_base_init (void);
/*Ephemeron functionality. Sgen only*/
gboolean mono_gc_ephemeron_array_add (MonoObject *obj);
- /* To disable synchronous, evacuating collections - concurrent SGen only */
- gboolean mono_gc_set_allow_synchronous_major (gboolean flag);
-
MonoBoolean
mono_gc_GCHandle_CheckCurrentDomain (guint32 gchandle);
#include <mono/metadata/marshal.h> /* for mono_delegate_free_ftnptr () */
#include <mono/metadata/attach.h>
#include <mono/metadata/console-io.h>
-#include <mono/utils/mono-semaphore.h>
+#include <mono/utils/mono-os-semaphore.h>
#include <mono/utils/mono-memory-model.h>
#include <mono/utils/mono-counters.h>
#include <mono/utils/mono-time.h>
#include <mono/utils/dtrace.h>
#include <mono/utils/mono-threads.h>
#include <mono/utils/atomic.h>
+#include <mono/utils/mono-coop-semaphore.h>
#ifndef HOST_WIN32
#include <pthread.h>
gboolean mono_do_not_finalize = FALSE;
gchar **mono_do_not_finalize_class_names = NULL;
-#define mono_finalizer_lock() mono_mutex_lock (&finalizer_mutex)
-#define mono_finalizer_unlock() mono_mutex_unlock (&finalizer_mutex)
-static mono_mutex_t finalizer_mutex;
-static mono_mutex_t reference_queue_mutex;
+#define mono_finalizer_lock() mono_coop_mutex_lock (&finalizer_mutex)
+#define mono_finalizer_unlock() mono_coop_mutex_unlock (&finalizer_mutex)
+static MonoCoopMutex finalizer_mutex;
+static MonoCoopMutex reference_queue_mutex;
static GSList *domains_to_finalize= NULL;
static MonoMList *threads_to_finalize = NULL;
static gboolean finalizer_thread_exited;
/* Uses finalizer_mutex */
-static mono_cond_t exited_cond;
+static MonoCoopCond exited_cond;
static MonoInternalThread *gc_thread;
* end up running them while or after the domain is being cleared, so
* the objects will not be valid anymore.
*/
- if (!mono_domain_is_unloading (domain)) {
- MONO_TRY_BLOCKING;
+ if (!mono_domain_is_unloading (domain))
mono_gc_register_for_finalization (obj, callback);
- MONO_FINISH_TRY_BLOCKING;
- }
#endif
}
return mono_domain_get ()->ephemeron_tombstone;
}
-#define mono_allocator_lock() mono_mutex_lock (&allocator_section)
-#define mono_allocator_unlock() mono_mutex_unlock (&allocator_section)
-static mono_mutex_t allocator_section;
-
MonoObject *
ves_icall_System_GCHandle_GetTarget (guint32 handle)
{
return NULL;
}
- MonoBoolean
- ves_icall_Mono_Runtime_SetGCAllowSynchronousMajor (MonoBoolean flag)
- {
- return mono_gc_set_allow_synchronous_major (flag);
- }
-
MonoBoolean
mono_gc_GCHandle_CheckCurrentDomain (guint32 gchandle)
{
return mono_gchandle_is_in_domain (gchandle, mono_domain_get ());
}
-#ifdef MONO_HAS_SEMAPHORES
-static MonoSemType finalizer_sem;
-#endif
-static HANDLE finalizer_event;
+static MonoCoopSem finalizer_sem;
static volatile gboolean finished=FALSE;
void
if (mono_gc_is_null ())
return;
-#ifdef MONO_HAS_SEMAPHORES
- MONO_SEM_POST (&finalizer_sem);
-#else
- SetEvent (finalizer_event);
-#endif
+ mono_coop_sem_post (&finalizer_sem);
}
#ifdef HAVE_BOEHM_GC
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 */
-#ifdef MONO_HAS_SEMAPHORES
- MONO_SEM_WAIT_ALERTABLE (&finalizer_sem, TRUE);
-#else
- WaitForSingleObjectEx (finalizer_event, INFINITE, TRUE);
-#endif
+ /* An alertable wait is required so this thread can be suspended on windows */
+ mono_coop_sem_wait (&finalizer_sem, MONO_SEM_FLAGS_ALERTABLE);
}
wait = TRUE;
- MONO_FINISH_BLOCKING;
+
mono_gc_set_skip_thread (FALSE);
mono_threads_perform_thread_dump ();
reference_queue_proccess_all ();
-#ifdef MONO_HAS_SEMAPHORES
/* Avoid posting the pending done event until there are pending finalizers */
- if (MONO_SEM_TIMEDWAIT (&finalizer_sem, 0) == 0)
+ if (mono_coop_sem_timedwait (&finalizer_sem, 0, MONO_SEM_FLAGS_NONE) == 0) {
/* Don't wait again at the start of the loop */
wait = FALSE;
- else
- SetEvent (pending_done_event);
-#else
+ } else {
SetEvent (pending_done_event);
-#endif
+ }
}
mono_finalizer_lock ();
finalizer_thread_exited = TRUE;
- mono_cond_signal (&exited_cond);
+ mono_coop_cond_signal (&exited_cond);
mono_finalizer_unlock ();
return 0;
void
mono_gc_init (void)
{
- mono_mutex_init_recursive (&allocator_section);
-
- mono_mutex_init_recursive (&finalizer_mutex);
- mono_mutex_init_recursive (&reference_queue_mutex);
+ mono_coop_mutex_init_recursive (&finalizer_mutex);
+ mono_coop_mutex_init_recursive (&reference_queue_mutex);
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);
gc_disabled = TRUE;
return;
}
-
- finalizer_event = CreateEvent (NULL, FALSE, FALSE, NULL);
- g_assert (finalizer_event);
+
pending_done_event = CreateEvent (NULL, TRUE, FALSE, NULL);
g_assert (pending_done_event);
- mono_cond_init (&exited_cond, 0);
-#ifdef MONO_HAS_SEMAPHORES
- MONO_SEM_INIT (&finalizer_sem, 0);
-#endif
+ mono_coop_cond_init (&exited_cond);
+ mono_coop_sem_init (&finalizer_sem, 0);
#ifndef LAZY_GC_THREAD_CREATION
mono_gc_init_finalizer_thread ();
break;
else
timeout = end_ticks - current_ticks;
- MONO_PREPARE_BLOCKING;
mono_finalizer_lock ();
if (!finalizer_thread_exited)
- mono_cond_timedwait_ms (&exited_cond, &finalizer_mutex, timeout);
+ mono_coop_cond_timedwait (&exited_cond, &finalizer_mutex, timeout);
mono_finalizer_unlock ();
- MONO_FINISH_BLOCKING;
}
if (!finalizer_thread_exited) {
mono_reference_queue_cleanup ();
- mono_mutex_destroy (&allocator_section);
- mono_mutex_destroy (&finalizer_mutex);
- mono_mutex_destroy (&reference_queue_mutex);
+ mono_coop_mutex_destroy (&finalizer_mutex);
+ mono_coop_mutex_destroy (&reference_queue_mutex);
}
gboolean
reference_queue_proccess (queue);
restart:
- mono_mutex_lock (&reference_queue_mutex);
+ mono_coop_mutex_lock (&reference_queue_mutex);
for (iter = &ref_queues; *iter;) {
queue = *iter;
if (!queue->should_be_deleted) {
continue;
}
if (queue->queue) {
- mono_mutex_unlock (&reference_queue_mutex);
+ mono_coop_mutex_unlock (&reference_queue_mutex);
reference_queue_proccess (queue);
goto restart;
}
*iter = queue->next;
g_free (queue);
}
- mono_mutex_unlock (&reference_queue_mutex);
+ mono_coop_mutex_unlock (&reference_queue_mutex);
}
static void
MonoReferenceQueue *res = g_new0 (MonoReferenceQueue, 1);
res->callback = callback;
- mono_mutex_lock (&reference_queue_mutex);
+ mono_coop_mutex_lock (&reference_queue_mutex);
res->next = ref_queues;
ref_queues = res;
- mono_mutex_unlock (&reference_queue_mutex);
+ mono_coop_mutex_unlock (&reference_queue_mutex);
return res;
}
#include "utils/mono-counters.h"
#include "utils/mono-logger-internals.h"
#include "utils/mono-time.h"
-#include "utils/mono-semaphore.h"
+#include "utils/mono-os-semaphore.h"
#include "metadata/sgen-bridge-internals.h"
extern void mono_sgen_register_moved_object (void *obj, void *destination);
else
element_size = vtable->klass->sizes.element_size;
- size_without_bounds = size = sizeof (MonoArray) + element_size * mono_array_length_fast (array);
+ size_without_bounds = size = MONO_SIZEOF_MONO_ARRAY + element_size * mono_array_length_fast (array);
if (G_UNLIKELY (array->bounds)) {
size += sizeof (mono_array_size_t) - 1;
#endif
}
+ static void G_GNUC_UNUSED
+ sgen_client_binary_protocol_mod_union_remset (gpointer obj, gpointer ptr, gpointer value, gpointer value_vtable)
+ {
+ }
+
static void G_GNUC_UNUSED
sgen_client_binary_protocol_ptr_update (gpointer ptr, gpointer old_value, gpointer new_value, gpointer vtable, size_t size)
{
typedef MonoSemType SgenSemaphore;
-#define SGEN_SEMAPHORE_INIT(sem,initial) MONO_SEM_INIT ((sem), (initial))
-#define SGEN_SEMAPHORE_POST(sem) MONO_SEM_POST ((sem))
-#define SGEN_SEMAPHORE_WAIT(sem) MONO_SEM_WAIT ((sem))
+#define SGEN_SEMAPHORE_INIT(sem,initial) mono_os_sem_init ((sem), (initial))
+#define SGEN_SEMAPHORE_POST(sem) mono_os_sem_post ((sem))
+#define SGEN_SEMAPHORE_WAIT(sem) mono_os_sem_wait ((sem), MONO_SEM_FLAGS_NONE)
gboolean sgen_has_critical_method (void);
gboolean sgen_is_critical_method (MonoMethod *method);
klass.element_class = mono_defaults.byte_class;
klass.rank = 1;
- klass.instance_size = sizeof (MonoArray);
+ klass.instance_size = MONO_SIZEOF_MONO_ARRAY;
klass.sizes.element_size = 1;
klass.name = "array_filler_type";
{
MonoArray *o;
- if (size < sizeof (MonoArray)) {
+ if (size < MONO_SIZEOF_MONO_ARRAY) {
memset (start, 0, size);
return FALSE;
}
/* Mark this as not a real object */
o->obj.synchronisation = GINT_TO_POINTER (-1);
o->bounds = NULL;
- o->max_length = (mono_array_size_t)(size - sizeof (MonoArray));
+ o->max_length = (mono_array_size_t)(size - MONO_SIZEOF_MONO_ARRAY);
return TRUE;
}
void
sgen_client_zero_array_fill_header (void *p, size_t size)
{
- if (size >= sizeof (MonoArray)) {
- memset (p, 0, sizeof (MonoArray));
+ if (size >= MONO_SIZEOF_MONO_ARRAY) {
+ memset (p, 0, MONO_SIZEOF_MONO_ARRAY);
} else {
- static guint8 zeros [sizeof (MonoArray)];
+ static guint8 zeros [MONO_SIZEOF_MONO_ARRAY];
SGEN_ASSERT (0, !memcmp (p, zeros, size), "TLAB segment must be zeroed out.");
}
mono_mb_emit_ldarg (mb, 1);
mono_mb_emit_byte (mb, CEE_MUL_OVF_UN);
/* + sizeof (MonoArray) */
- mono_mb_emit_icon (mb, sizeof (MonoArray));
+ mono_mb_emit_icon (mb, MONO_SIZEOF_MONO_ARRAY);
mono_mb_emit_byte (mb, CEE_ADD_OVF_UN);
mono_mb_emit_stloc (mb, size_var);
mono_gc_wait_for_bridge_processing ();
}
- gboolean
- mono_gc_set_allow_synchronous_major (gboolean flag)
- {
- return sgen_set_allow_synchronous_major (flag);
- }
-
void*
mono_gc_invoke_with_gc_lock (MonoGCLockedCallbackFunc func, void *data)
{
each collection */
static gboolean do_scan_starts_check = FALSE;
- /*
- * If the major collector is concurrent and this is FALSE, we will
- * never initiate a synchronous major collection, unless requested via
- * GC.Collect().
- */
- static gboolean allow_synchronous_major = TRUE;
static gboolean disable_minor_collections = FALSE;
static gboolean disable_major_collections = FALSE;
static gboolean do_verify_nursery = FALSE;
* ######## Global data.
* ######################################################################
*/
-LOCK_DECLARE (gc_mutex);
+MonoCoopMutex gc_mutex;
gboolean sgen_try_free_some_memory;
#define SCAN_START_SIZE SGEN_SCAN_START_SIZE
static volatile mword lowest_heap_address = ~(mword)0;
static volatile mword highest_heap_address = 0;
-LOCK_DECLARE (sgen_interruption_mutex);
+MonoCoopMutex sgen_interruption_mutex;
int current_collection_generation = -1;
static volatile gboolean concurrent_collection_in_progress = FALSE;
goto done;
}
- /*
- * If we've been asked to do a major collection, and the major collector wants to
- * run synchronously (to evacuate), we set the flag to do that.
- */
- if (generation_to_collect == GENERATION_OLD &&
- allow_synchronous_major &&
- major_collector.want_synchronous_collection &&
- *major_collector.want_synchronous_collection) {
- wait_to_finish = TRUE;
- }
-
SGEN_ASSERT (0, !concurrent_collection_in_progress, "Why did this not get handled above?");
/*
return tot;
}
- gboolean
- sgen_set_allow_synchronous_major (gboolean flag)
- {
- if (!major_collector.is_concurrent)
- return flag;
-
- allow_synchronous_major = flag;
- return TRUE;
- }
-
void
sgen_env_var_error (const char *env_var, const char *fallback, const char *description_format, ...)
{
mono_thread_smr_init ();
#endif
- LOCK_INIT (gc_mutex);
+ mono_coop_mutex_init (&gc_mutex);
gc_debug_file = stderr;
- LOCK_INIT (sgen_interruption_mutex);
+ mono_coop_mutex_init (&sgen_interruption_mutex);
if ((env = g_getenv (MONO_GC_PARAMS_NAME))) {
opts = g_strsplit (env, ",", -1);
}
continue;
}
- if (g_str_has_prefix (opt, "allow-synchronous-major=")) {
- if (!major_collector.is_concurrent) {
- sgen_env_var_error (MONO_GC_PARAMS_NAME, "Ignoring.", "`allow-synchronous-major` is only valid for the concurrent major collector.");
- continue;
- }
-
- opt = strchr (opt, '=') + 1;
-
- if (!strcmp (opt, "yes")) {
- allow_synchronous_major = TRUE;
- } else if (!strcmp (opt, "no")) {
- allow_synchronous_major = FALSE;
- } else {
- sgen_env_var_error (MONO_GC_PARAMS_NAME, "Using default value.", "`allow-synchronous-major` must be either `yes' or `no'.");
- continue;
- }
- }
if (!strcmp (opt, "cementing")) {
cement_enabled = TRUE;
fprintf (stderr, " minor=COLLECTOR (where COLLECTOR is `simple' or `split')\n");
fprintf (stderr, " wbarrier=WBARRIER (where WBARRIER is `remset' or `cardtable')\n");
fprintf (stderr, " [no-]cementing\n");
- if (major_collector.is_concurrent)
- fprintf (stderr, " allow-synchronous-major=FLAG (where FLAG is `yes' or `no')\n");
if (major_collector.print_gc_param_usage)
major_collector.print_gc_param_usage ();
if (sgen_minor_collector.print_gc_param_usage)
void
sgen_gc_lock (void)
{
- LOCK_GC;
+ mono_coop_mutex_lock (&gc_mutex);
}
void
{
gboolean try_free = sgen_try_free_some_memory;
sgen_try_free_some_memory = FALSE;
- mono_mutex_unlock (&gc_mutex);
+ mono_coop_mutex_unlock (&gc_mutex);
if (try_free)
mono_thread_hazardous_try_free_some ();
}
#include <stdint.h>
#include "mono/utils/mono-compiler.h"
#include "mono/utils/atomic.h"
-#include "mono/utils/mono-mutex.h"
+#include "mono/utils/mono-os-mutex.h"
+#include "mono/utils/mono-coop-mutex.h"
#include "mono/sgen/sgen-conf.h"
#include "mono/sgen/sgen-hash-table.h"
#include "mono/sgen/sgen-protocol.h"
#define LOCK_DECLARE(name) mono_mutex_t name
/* if changing LOCK_INIT to something that isn't idempotent, look at
its use in mono_gc_base_init in sgen-gc.c */
-#define LOCK_INIT(name) mono_mutex_init (&(name))
-#define LOCK_GC do { \
- MONO_TRY_BLOCKING \
- mono_mutex_lock (&gc_mutex); \
- MONO_FINISH_TRY_BLOCKING \
- } while (0)
+#define LOCK_INIT(name) mono_os_mutex_init (&(name))
+#define LOCK_GC do { sgen_gc_lock (); } while (0)
#define UNLOCK_GC do { sgen_gc_unlock (); } while (0)
-extern LOCK_DECLARE (sgen_interruption_mutex);
-
-#define LOCK_INTERRUPTION do { \
- MONO_TRY_BLOCKING \
- mono_mutex_lock (&sgen_interruption_mutex); \
- MONO_FINISH_TRY_BLOCKING \
-} while (0)
+extern MonoCoopMutex sgen_interruption_mutex;
-#define UNLOCK_INTERRUPTION mono_mutex_unlock (&sgen_interruption_mutex)
+#define LOCK_INTERRUPTION mono_coop_mutex_lock (&sgen_interruption_mutex)
+#define UNLOCK_INTERRUPTION mono_coop_mutex_unlock (&sgen_interruption_mutex)
/* FIXME: Use InterlockedAdd & InterlockedAdd64 to reduce the CAS cost. */
#define SGEN_CAS InterlockedCompareExchange
gboolean supports_cardtable;
gboolean sweeps_lazily;
- /*
- * This is set to TRUE by the sweep if the next major
- * collection should be synchronous (for evacuation). For
- * non-concurrent collectors, this should be NULL.
- */
- gboolean *want_synchronous_collection;
-
void* (*alloc_heap) (mword nursery_size, mword nursery_align, int nursery_bits);
gboolean (*is_object_live) (GCObject *obj);
GCObject* (*alloc_small_pinned_obj) (GCVTable vtable, size_t size, gboolean has_references);
extern NurseryClearPolicy nursery_clear_policy;
extern gboolean sgen_try_free_some_memory;
-extern LOCK_DECLARE (gc_mutex);
+extern MonoCoopMutex gc_mutex;
/* Nursery helpers. */
static gboolean *evacuate_block_obj_sizes;
static float evacuation_threshold = 0.666f;
- static float concurrent_evacuation_threshold = 0.666f;
- static gboolean want_evacuation = FALSE;
static gboolean lazy_sweep = FALSE;
static guint64 stat_major_blocks_alloced = 0;
static guint64 stat_major_blocks_freed = 0;
static guint64 stat_major_blocks_lazy_swept = 0;
- static guint64 stat_major_objects_evacuated = 0;
#if SIZEOF_VOID_P != 8
static guint64 stat_major_blocks_freed_ideal = 0;
if (!binary_protocol_is_enabled ())
return;
- mono_mutex_lock (&scanned_objects_list_lock);
+ mono_os_mutex_lock (&scanned_objects_list_lock);
sgen_pointer_queue_add (&scanned_objects_list, ptr);
- mono_mutex_unlock (&scanned_objects_list_lock);
+ mono_os_mutex_unlock (&scanned_objects_list_lock);
}
#endif
* Blocks that are to-space are not evacuated from. During an major collection
* blocks are allocated for two reasons: evacuating objects from the nursery and
* evacuating them from major blocks marked for evacuation. In both cases we don't
- * want further evacuation.
+ * want further evacuation. We also don't want to evacuate objects allocated during
+ * the concurrent mark since it would add pointless stress on the finishing pause.
*/
- info->is_to_space = (sgen_get_current_collection_generation () == GENERATION_OLD);
- info->state = (info->is_to_space || sgen_concurrent_collection_in_progress ()) ? BLOCK_STATE_MARKING : BLOCK_STATE_SWEPT;
+ info->is_to_space = (sgen_get_current_collection_generation () == GENERATION_OLD) || sgen_concurrent_collection_in_progress ();
+ info->state = info->is_to_space ? BLOCK_STATE_MARKING : BLOCK_STATE_SWEPT;
SGEN_ASSERT (6, !sweep_in_progress () || info->state == BLOCK_STATE_SWEPT, "How do we add a new block to be swept while sweeping?");
info->cardtable_mod_union = NULL;
* Mark the mod-union card for `ptr`, which must be a reference within the object `obj`.
*/
static void
- mark_mod_union_card (GCObject *obj, void **ptr)
+ mark_mod_union_card (GCObject *obj, void **ptr, GCObject *value_obj)
{
int type = sgen_obj_get_descriptor (obj) & DESC_TYPE_MASK;
if (sgen_safe_object_is_small (obj, type)) {
} else {
sgen_los_mark_mod_union_card (obj, ptr);
}
+
+ binary_protocol_mod_union_remset (obj, ptr, value_obj, SGEN_LOAD_VTABLE (value_obj));
+ }
+
+ static inline gboolean
+ major_block_is_evacuating (MSBlockInfo *block)
+ {
+ if (evacuate_block_obj_sizes [block->obj_size_index] &&
+ !block->has_pinned &&
+ !block->is_to_space)
+ return TRUE;
+ return FALSE;
}
#define LOAD_VTABLE SGEN_LOAD_VTABLE
static guint64 stat_drain_loops;
#endif
- static void major_scan_object_with_evacuation (GCObject *start, mword desc, SgenGrayQueue *queue);
-
#define COPY_OR_MARK_FUNCTION_NAME major_copy_or_mark_object_no_evacuation
#define SCAN_OBJECT_FUNCTION_NAME major_scan_object_no_evacuation
#define DRAIN_GRAY_STACK_FUNCTION_NAME drain_gray_stack_no_evacuation
static void
major_copy_or_mark_object_concurrent_finish_canonical (GCObject **ptr, SgenGrayQueue *queue)
{
- major_copy_or_mark_object_no_evacuation (ptr, *ptr, queue);
+ major_copy_or_mark_object_with_evacuation (ptr, *ptr, queue);
}
static void
static void
sweep_finish (void)
{
- mword total_evacuate_heap = 0;
- mword total_evacuate_saved = 0;
int i;
for (i = 0; i < num_block_obj_sizes; ++i) {
} else {
evacuate_block_obj_sizes [i] = FALSE;
}
- {
- mword total_bytes = block_obj_sizes [i] * sweep_slots_available [i];
- total_evacuate_heap += total_bytes;
- if (evacuate_block_obj_sizes [i])
- total_evacuate_saved += total_bytes - block_obj_sizes [i] * sweep_slots_used [i];
- }
}
- want_evacuation = (float)total_evacuate_saved / (float)total_evacuate_heap > (1 - concurrent_evacuation_threshold);
-
set_sweep_state (SWEEP_STATE_SWEPT, SWEEP_STATE_COMPACTING);
}
mono_counters_register ("# major blocks allocated", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_major_blocks_alloced);
mono_counters_register ("# major blocks freed", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_major_blocks_freed);
mono_counters_register ("# major blocks lazy swept", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_major_blocks_lazy_swept);
- mono_counters_register ("# major objects evacuated", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_major_objects_evacuated);
#if SIZEOF_VOID_P != 8
mono_counters_register ("# major blocks freed ideally", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_major_blocks_freed_ideal);
mono_counters_register ("# major blocks freed less ideally", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_major_blocks_freed_less_ideal);
concurrent_mark = is_concurrent;
collector->is_concurrent = is_concurrent;
collector->needs_thread_pool = is_concurrent || concurrent_sweep;
- if (is_concurrent)
- collector->want_synchronous_collection = &want_evacuation;
- else
- collector->want_synchronous_collection = NULL;
collector->get_and_reset_num_major_objects_marked = major_get_and_reset_num_major_objects_marked;
collector->supports_cardtable = TRUE;
collector->major_ops_concurrent_start.drain_gray_stack = drain_gray_stack_concurrent;
collector->major_ops_concurrent_finish.copy_or_mark_object = major_copy_or_mark_object_concurrent_finish_canonical;
- collector->major_ops_concurrent_finish.scan_object = major_scan_object_no_evacuation;
+ collector->major_ops_concurrent_finish.scan_object = major_scan_object_with_evacuation;
collector->major_ops_concurrent_finish.scan_vtype = major_scan_vtype_concurrent_finish;
- collector->major_ops_concurrent_finish.drain_gray_stack = drain_gray_stack_no_evacuation;
+ collector->major_ops_concurrent_finish.drain_gray_stack = drain_gray_stack;
}
#ifdef HEAVY_STATISTICS
mono_counters_register ("Optimized copy major", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_optimized_copy_major);
mono_counters_register ("Optimized copy major small fast", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_optimized_copy_major_small_fast);
mono_counters_register ("Optimized copy major small slow", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_optimized_copy_major_small_slow);
+ mono_counters_register ("Optimized copy major small evacuate", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_optimized_copy_major_small_evacuate);
mono_counters_register ("Optimized copy major large", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_optimized_copy_major_large);
mono_counters_register ("Optimized major scan", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_optimized_major_scan);
mono_counters_register ("Optimized major scan no refs", MONO_COUNTER_GC | MONO_COUNTER_ULONG, &stat_optimized_major_scan_no_refs);
#endif
#ifdef SGEN_HEAVY_BINARY_PROTOCOL
- mono_mutex_init (&scanned_objects_list_lock);
+ mono_os_mutex_init (&scanned_objects_list_lock);
#endif
SGEN_ASSERT (0, SGEN_MAX_SMALL_OBJ_SIZE <= MS_BLOCK_FREE / 2, "MAX_SMALL_OBJ_SIZE must be at most MS_BLOCK_FREE / 2");