* ######################################################################
*/
LOCK_DECLARE (gc_mutex);
+gboolean sgen_try_free_some_memory;
#define SCAN_START_SIZE SGEN_SCAN_START_SIZE
return TRUE;
#ifndef DISABLE_REMOTING
- if (mono_class_has_parent_fast (o->vtable->klass, mono_defaults.real_proxy_class) &&
+ if (mono_defaults.real_proxy_class->supertypes && mono_class_has_parent_fast (o->vtable->klass, mono_defaults.real_proxy_class) &&
offset == G_STRUCT_OFFSET (MonoRealProxy, unwrapped_server))
return TRUE;
#endif
/* The object could be a proxy for an object in the domain
we're deleting. */
#ifndef DISABLE_REMOTING
- if (mono_class_has_parent_fast (vt->klass, mono_defaults.real_proxy_class)) {
+ if (mono_defaults.real_proxy_class->supertypes && mono_class_has_parent_fast (vt->klass, mono_defaults.real_proxy_class)) {
MonoObject *server = ((MonoRealProxy*)start)->unwrapped_server;
/* The server could already have been zeroed out, so
++ephemeron_rounds;
} while (!done_with_ephemerons);
- sgen_scan_togglerefs (start_addr, end_addr, ctx);
+ sgen_mark_togglerefs (start_addr, end_addr, ctx);
if (sgen_need_bridge_processing ()) {
/*Make sure the gray stack is empty before we process bridge objects so we get liveness right*/
*/
clear_unreachable_ephemerons (ctx);
+ /*
+ * We clear togglerefs only after all possible chances of revival are done.
+ * This is semantically more inline with what users expect and it allows for
+ * user finalizers to correctly interact with TR objects.
+ */
+ sgen_clear_togglerefs (start_addr, end_addr, ctx);
+
TV_GETTIME (btv);
SGEN_LOG (2, "Finalize queue handling scan for %s generation: %d usecs %d ephemeron rounds", generation_name (generation), TV_ELAPSED (atv, btv), ephemeron_rounds);
continue;
}
sgen_los_pin_object (bigobj->data);
- /* FIXME: only enqueue if object has references */
- GRAY_OBJECT_ENQUEUE (WORKERS_DISTRIBUTE_GRAY_QUEUE, bigobj->data);
+ if (SGEN_OBJECT_HAS_REFERENCES (bigobj->data))
+ GRAY_OBJECT_ENQUEUE (WORKERS_DISTRIBUTE_GRAY_QUEUE, bigobj->data);
if (G_UNLIKELY (do_pin_stats))
sgen_pin_stats_register_object ((char*) bigobj->data, safe_object_get_size ((MonoObject*) bigobj->data));
SGEN_LOG (6, "Marked large object %p (%s) size: %lu from roots", bigobj->data, safe_name (bigobj->data), (unsigned long)sgen_los_object_size (bigobj));
static void*
sgen_thread_register (SgenThreadInfo* info, void *addr)
{
+ size_t stsize = 0;
+ guint8 *staddr = NULL;
+
#ifndef HAVE_KW_THREAD
info->tlab_start = info->tlab_next = info->tlab_temp_end = info->tlab_real_end = NULL;
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)
- {
- size_t size;
- void *sstart;
- pthread_attr_t attr;
-
-#if defined(HAVE_PTHREAD_GETATTR_NP)
- /* Linux */
- pthread_getattr_np (pthread_self (), &attr);
-#elif defined(HAVE_PTHREAD_ATTR_GET_NP)
- /* BSD */
- pthread_attr_init (&attr);
- pthread_attr_get_np (pthread_self (), &attr);
-#else
-#error Cannot determine which API is needed to retrieve pthread attributes.
+ /* On win32, stack_start_limit should be 0, since the stack can grow dynamically */
+#ifndef HOST_WIN32
+ mono_thread_info_get_stack_bounds (&staddr, &stsize);
#endif
-
- pthread_attr_getstack (&attr, &sstart, &size);
- info->stack_start_limit = sstart;
- info->stack_end = (char*)sstart + size;
- pthread_attr_destroy (&attr);
- }
-#elif defined(HAVE_PTHREAD_GET_STACKSIZE_NP) && defined(HAVE_PTHREAD_GET_STACKADDR_NP)
- {
- size_t stsize = 0;
- guint8 *staddr = NULL;
-
- mono_thread_get_stack_bounds (&staddr, &stsize);
+ if (staddr) {
info->stack_start_limit = staddr;
info->stack_end = staddr + stsize;
- }
-#else
- {
- /* FIXME: we assume the stack grows down */
+ } else {
gsize stack_bottom = (gsize)addr;
stack_bottom += 4095;
stack_bottom &= ~4095;
info->stack_end = (char*)stack_bottom;
}
-#endif
#ifdef HAVE_KW_THREAD
stack_end = info->stack_end;
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));
+ MonoNativeThreadId tid;
+
+ tid = mono_thread_info_get_tid (p);
+ binary_protocol_thread_unregister ((gpointer)tid);
+ SGEN_LOG (3, "unregister thread %p (%p)", p, (gpointer)tid);
+
+ mono_threads_add_joinable_thread ((gpointer)tid);
if (gc_callbacks.thread_detach_func) {
gc_callbacks.thread_detach_func (p->runtime_data);
void
mono_gc_pthread_exit (void *retval)
{
- mono_thread_info_dettach ();
+ mono_thread_info_detach ();
pthread_exit (retval);
}
HEAVY_STAT (++stat_wbarrier_arrayref_copy);
/*This check can be done without taking a lock since dest_ptr array is pinned*/
if (ptr_in_nursery (dest_ptr) || count <= 0) {
- mono_gc_memmove (dest_ptr, src_ptr, count * sizeof (gpointer));
+ mono_gc_memmove_aligned (dest_ptr, src_ptr, count * sizeof (gpointer));
return;
}
if (ptr_in_nursery (dest) || ptr_on_stack (dest) || !SGEN_CLASS_HAS_REFERENCES (klass)) {
size_t element_size = mono_class_value_size (klass, NULL);
size_t size = count * element_size;
- mono_gc_memmove (dest, src, size);
+ mono_gc_memmove_atomic (dest, src, size);
return;
}
if (ptr_in_nursery (obj) || ptr_on_stack (obj)) {
size = mono_object_class (obj)->instance_size;
- mono_gc_memmove ((char*)obj + sizeof (MonoObject), (char*)src + sizeof (MonoObject),
+ mono_gc_memmove_aligned ((char*)obj + sizeof (MonoObject), (char*)src + sizeof (MonoObject),
size - sizeof (MonoObject));
return;
}
cb.thread_attach = sgen_thread_attach;
cb.mono_method_is_critical = (gpointer)is_critical_method;
#ifndef HOST_WIN32
+ cb.thread_exit = mono_gc_pthread_exit;
cb.mono_gc_pthread_create = (gpointer)mono_gc_pthread_create;
#endif
sgen_register_test_bridge_callbacks (g_strdup (opt));
continue;
}
+ if (g_str_has_prefix (opt, "toggleref-test")) {
+ sgen_register_test_toggleref_callback ();
+ continue;
+ }
+
#ifdef USER_CONFIG
if (g_str_has_prefix (opt, "nursery-size=")) {
long val;
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
guint
mono_gc_get_vtable_bits (MonoClass *class)
{
- if (sgen_need_bridge_processing () && sgen_is_bridge_class (class))
+ /* FIXME move this to the bridge code */
+ if (!sgen_need_bridge_processing ())
+ return 0;
+ switch (sgen_bridge_class_kind (class)) {
+ case GC_BRIDGE_TRANSPARENT_BRIDGE_CLASS:
+ case GC_BRIDGE_OPAQUE_BRIDGE_CLASS:
return SGEN_GC_BIT_BRIDGE_OBJECT;
+ }
return 0;
}