* ######################################################################
*/
LOCK_DECLARE (gc_mutex);
+gboolean sgen_try_free_some_memory;
#define SCAN_START_SIZE SGEN_SCAN_START_SIZE
static void
wait_for_workers_to_finish (void)
+{
+ while (!sgen_workers_all_done ())
+ g_usleep (200);
+}
+
+static void
+join_workers (void)
{
if (concurrent_collection_in_progress || major_collector.is_parallel) {
gray_queue_redirect (&gray_queue);
TV_GETTIME (btv);
if (concurrent_collection_in_progress || major_collector.is_parallel)
- wait_for_workers_to_finish ();
+ join_workers ();
if (concurrent_collection_in_progress) {
current_object_ops = major_collector.major_concurrent_ops;
major_copy_or_mark_from_roots (NULL, TRUE, scan_mod_union);
- wait_for_workers_to_finish ();
+ join_workers ();
g_assert (sgen_gray_object_queue_is_empty (&gray_queue));
g_assert (sgen_gray_object_queue_is_empty (&gray_queue));
- major_collector.update_cardtable_mod_union ();
- sgen_los_update_cardtable_mod_union ();
-
if (!force_finish && !sgen_workers_all_done ()) {
+ major_collector.update_cardtable_mod_union ();
+ sgen_los_update_cardtable_mod_union ();
+
MONO_GC_CONCURRENT_UPDATE_END (GENERATION_OLD, major_collector.get_and_reset_num_major_objects_marked ());
return FALSE;
}
- if (mod_union_consistency_check)
- sgen_check_mod_union_consistency ();
+ /*
+ * The major collector can add global remsets which are processed in the finishing
+ * nursery collection, below. That implies that the workers must have finished
+ * marking before the nursery collection is allowed to run, otherwise we might miss
+ * some remsets.
+ */
+ wait_for_workers_to_finish ();
+
+ major_collector.update_cardtable_mod_union ();
+ sgen_los_update_cardtable_mod_union ();
collect_nursery (&unpin_queue, TRUE);
+ if (mod_union_consistency_check)
+ sgen_check_mod_union_consistency ();
+
current_collection_generation = GENERATION_OLD;
major_finish_collection ("finishing", -1, TRUE);
binary_protocol_thread_register ((gpointer)mono_thread_info_get_tid (info));
+ // FIXME: Unift with mono_thread_get_stack_bounds ()
/* try to get it with attributes first */
#if (defined(HAVE_PTHREAD_GETATTR_NP) || defined(HAVE_PTHREAD_ATTR_GET_NP)) && defined(HAVE_PTHREAD_ATTR_GETSTACK)
{
pthread_attr_destroy (&attr);
}
#elif defined(HAVE_PTHREAD_GET_STACKSIZE_NP) && defined(HAVE_PTHREAD_GET_STACKADDR_NP)
- info->stack_end = (char*)pthread_get_stackaddr_np (pthread_self ());
- info->stack_start_limit = (char*)info->stack_end - pthread_get_stacksize_np (pthread_self ());
+ {
+ size_t stsize = 0;
+ guint8 *staddr = NULL;
+
+ mono_thread_get_stack_bounds (&staddr, &stsize);
+ info->stack_start_limit = staddr;
+ info->stack_end = staddr + stsize;
+ }
#else
{
/* FIXME: we assume the stack grows down */
}
static void
-sgen_thread_unregister (SgenThreadInfo *p)
+sgen_thread_detach (SgenThreadInfo *p)
{
/* If a delegate is passed to native code and invoked on a thread we dont
* know about, the jit will register it with mono_jit_thread_attach, but
*/
if (mono_domain_get ())
mono_thread_detach (mono_thread_current ());
+}
+static void
+sgen_thread_unregister (SgenThreadInfo *p)
+{
binary_protocol_thread_unregister ((gpointer)mono_thread_info_get_tid (p));
SGEN_LOG (3, "unregister thread %p (%p)", p, (gpointer)mono_thread_info_get_tid (p));
SGEN_LOG (8, "Wbarrier atomic store at %p to %p (%s)", ptr, value, value ? safe_name (value) : "null");
- mono_atomic_store_release ((volatile MonoObject **) ptr, value);
+ InterlockedWritePointer (ptr, value);
if (ptr_in_nursery (value))
mono_gc_wbarrier_generic_nostore (ptr);
gc_debug_file = stderr;
cb.thread_register = sgen_thread_register;
+ cb.thread_detach = sgen_thread_detach;
cb.thread_unregister = sgen_thread_unregister;
cb.thread_attach = sgen_thread_attach;
cb.mono_method_is_critical = (gpointer)is_critical_method;
res = mono_mb_create_method (mb, sig, 16);
mono_mb_free (mb);
- mono_loader_lock ();
+ LOCK_GC;
if (write_barrier_method) {
/* Already created */
mono_free_method (res);
mono_memory_barrier ();
write_barrier_method = res;
}
- mono_loader_unlock ();
+ UNLOCK_GC;
return write_barrier_method;
}
void
sgen_gc_unlock (void)
{
- UNLOCK_GC;
+ gboolean try_free = sgen_try_free_some_memory;
+ sgen_try_free_some_memory = FALSE;
+ mono_mutex_unlock (&gc_mutex);
+ MONO_GC_UNLOCKED ();
+ if (try_free)
+ mono_thread_hazardous_try_free_some ();
}
void