[sgen] Complete the bridge weak reference fix.
authorMark Probst <mark.probst@gmail.com>
Tue, 2 Oct 2012 12:20:12 +0000 (14:20 +0200)
committerMark Probst <mark.probst@gmail.com>
Wed, 3 Oct 2012 17:48:39 +0000 (19:48 +0200)
When dereferencing a weak link we check whether bridge processing is
in progress.  If it is, we wait for it to finish.  This ensures that
we never follow weak links to dead objects before bridge processing
can null them.

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

index 5ad4b99a42909b40411a07dcf2b4f80daa8a2ac8..a4214a53f34ca8ad46e008aa70b774a5b280bd7d 100644 (file)
@@ -277,7 +277,7 @@ static MonoGCBridgeCallbacks bridge_callbacks;
 
 static int current_time;
 
-static gboolean bridge_processing_in_progress = FALSE;
+gboolean bridge_processing_in_progress = FALSE;
 
 void
 mono_gc_wait_for_bridge_processing (void)
@@ -554,6 +554,10 @@ sgen_bridge_processing_stw_step (void)
        if (!registered_bridges.size)
                return;
 
+       /*
+        * bridge_processing_in_progress must be set with the world
+        * stopped.  If not there would be race conditions.
+        */
        g_assert (!bridge_processing_in_progress);
        bridge_processing_in_progress = TRUE;
 
index cadcac0c7977e16c046e2430a755a4cbe72faff4..a79b307328c8d795955d1426a2712f37e4b7b5bf 100644 (file)
@@ -4423,6 +4423,18 @@ mono_gc_weak_link_get (void **link_addr)
        void *ptr = *link_addr;
        if (!ptr)
                return NULL;
+
+       /*
+        * During the second bridge processing step the world is
+        * running again.  That step processes all weak links once
+        * more to null those that refer to dead objects.  Before that
+        * is completed, those links must not be followed, so we
+        * conservatively wait for bridge processing when any weak
+        * link is dereferenced.
+        */
+       if (G_UNLIKELY (bridge_processing_in_progress))
+               mono_gc_wait_for_bridge_processing ();
+
        return (MonoObject*) REVEAL_POINTER (ptr);
 }
 
index 112572058ae4594558d6a81670ee8274535149b9..0f0e73440cc0f296d027baa9d8e96075e5d2c9eb 100644 (file)
@@ -256,6 +256,8 @@ extern int current_collection_generation;
 
 extern unsigned int sgen_global_stop_count;
 
+extern gboolean bridge_processing_in_progress;
+
 #define SGEN_ALLOC_ALIGN               8
 #define SGEN_ALLOC_ALIGN_BITS  3