[sgen]Fix a deadlock when the GC try to free a JI during world restart. Fixes #15759
authorRodrigo Kumpera <kumpera@gmail.com>
Fri, 6 Dec 2013 20:23:02 +0000 (15:23 -0500)
committerRodrigo Kumpera <kumpera@gmail.com>
Fri, 6 Dec 2013 20:23:02 +0000 (15:23 -0500)
This is deadlock prone as the GC lock is a leaf lock while the domain
lock required to free a JI is not.

There are plenty of places where we alloc memory while holding the
domain lock, so we cannot do it the other way.

mono/metadata/sgen-gc.c
mono/metadata/sgen-gc.h
mono/metadata/sgen-stw.c

index 0c0b15b75daad826c848f95f4f03461f91dd0b87..95f263c1c59c6313d50f4ac8aa3a47c4b8b2f1ab 100644 (file)
@@ -401,6 +401,7 @@ sgen_safe_name (void* obj)
  * ######################################################################
  */
 LOCK_DECLARE (gc_mutex);
+gboolean sgen_try_free_some_memory;
 
 #define SCAN_START_SIZE        SGEN_SCAN_START_SIZE
 
@@ -5597,7 +5598,12 @@ sgen_gc_lock (void)
 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
index 9f5902ea2688e43f2021249b8b7485473eb5edb9..15afdbcd03a2cd0f150b30b519127ada45bf40da 100644 (file)
@@ -158,10 +158,7 @@ struct _GCMemSection {
                MONO_GC_LOCKED ();                              \
        } while (0)
 #define TRYLOCK_GC (mono_mutex_trylock (&gc_mutex) == 0)
-#define UNLOCK_GC do {                                         \
-               mono_mutex_unlock (&gc_mutex);                  \
-               MONO_GC_UNLOCKED ();                            \
-       } while (0)
+#define UNLOCK_GC do { sgen_gc_unlock (); } while (0)
 
 extern LOCK_DECLARE (sgen_interruption_mutex);
 
@@ -979,6 +976,7 @@ extern int degraded_mode;
 extern int default_nursery_size;
 extern guint32 tlab_size;
 extern NurseryClearPolicy nursery_clear_policy;
+extern gboolean sgen_try_free_some_memory;
 
 extern LOCK_DECLARE (gc_mutex);
 
index 0f52505544c9184fe56b7574180933df1e8b95e1..54dc218b5848891e22c00f495f5b6de8a3093926 100755 (executable)
@@ -277,7 +277,7 @@ sgen_restart_world (int generation, GGTimingInfo *timing)
         */
        release_gc_locks ();
 
-       mono_thread_hazardous_try_free_some ();
+       sgen_try_free_some_memory = TRUE;
 
        sgen_bridge_processing_finish (generation);