[sgen] Fix race between block allocation and concurrent sweep.
authorVlad Brezae <brezaevlad@gmail.com>
Mon, 14 Sep 2015 22:39:03 +0000 (15:39 -0700)
committerVlad Brezae <brezaevlad@gmail.com>
Tue, 22 Sep 2015 07:38:29 +0000 (00:38 -0700)
Adding a new block to the allocated_blocks array is racy with the removal of nulls when sweeping. We wait for sweep to finish to avoid that.

This also handles the problem of allocating degraded objects while sweeping.

mono/sgen/sgen-marksweep.c

index 0cd42f7a79f405233430a80d78083265c5021c9c..55f40aba76e646cf0f18e0f0fbc4627b8c259d5a 100644 (file)
@@ -559,17 +559,14 @@ ms_alloc_block (int size_index, gboolean pinned, gboolean has_references)
        add_free_block (free_blocks, size_index, info);
 
        /*
-        * This is the only place where the `allocated_blocks` array can potentially grow.
-        * We need to make sure concurrent sweep isn't running when that happens, so in that
-        * specific case we just wait for sweep to finish.
+        * Adding to the allocated_blocks array is racy with the removal of nulls when
+        * sweeping. We wait for sweep to finish to avoid that.
         *
         * The memory barrier here and in `sweep_job_func()` are required because we need
         * `allocated_blocks` synchronized between this and the sweep thread.
         */
-       if (sgen_pointer_queue_will_grow (&allocated_blocks)) {
-               major_finish_sweep_checking ();
-               mono_memory_barrier ();
-       }
+       major_finish_sweep_checking ();
+       mono_memory_barrier ();
 
        sgen_pointer_queue_add (&allocated_blocks, BLOCK_TAG (info));
 
@@ -746,8 +743,6 @@ major_alloc_degraded (GCVTable vtable, size_t size)
 {
        GCObject *obj;
 
-       major_finish_sweep_checking ();
-
        obj = alloc_obj (vtable, size, FALSE, SGEN_VTABLE_HAS_REFERENCES (vtable));
        if (G_LIKELY (obj)) {
                HEAVY_STAT (++stat_objects_alloced_degraded);