[sgen] Add option for a new parallel concurrent collector
[mono.git] / mono / sgen / sgen-marksweep.c
index 8ae553c23b3d90687ef6ac7720a4e0d68127b155..9f0b24f4868e784a4a123003327f543df429de16 100644 (file)
@@ -188,7 +188,7 @@ static gboolean concurrent_sweep = TRUE;
 #define BLOCK_TAG(bl)                          ((bl)->has_references ? BLOCK_TAG_HAS_REFERENCES ((bl)) : (bl))
 
 /* all allocated blocks in the system */
-static SgenArrayList allocated_blocks = SGEN_ARRAY_LIST_INIT (NULL, NULL, NULL, INTERNAL_MEM_PIN_QUEUE);
+static SgenArrayList allocated_blocks = SGEN_ARRAY_LIST_INIT (NULL, sgen_array_list_default_is_slot_set, sgen_array_list_default_cas_setter, INTERNAL_MEM_PIN_QUEUE);
 
 /* non-allocated block free-list */
 static void *empty_blocks = NULL;
@@ -1417,8 +1417,6 @@ sweep_start (void)
                for (j = 0; j < num_block_obj_sizes; ++j)
                        free_blocks [j] = NULL;
        }
-
-       sgen_array_list_remove_nulls (&allocated_blocks);
 }
 
 static void sweep_finish (void);
@@ -1560,6 +1558,7 @@ ensure_block_is_checked_for_sweeping (guint32 block_index, gboolean wait, gboole
                ms_free_block (block);
 
                SGEN_ATOMIC_ADD_P (num_major_sections, -1);
+               SGEN_ATOMIC_ADD_P (num_major_sections_freed_in_sweep, 1);
 
                tagged_block = NULL;
        }
@@ -1606,13 +1605,8 @@ sweep_job_func (void *thread_data_untyped, SgenThreadPoolJob *job)
         * cooperate with the sweep thread to finish sweeping, and they will traverse from
         * low to high, to avoid constantly colliding on the same blocks.
         */
-       for (block_index = num_blocks; block_index-- > 0;) {
-               /*
-                * The block might have been freed by another thread doing some checking
-                * work.
-                */
-               if (!ensure_block_is_checked_for_sweeping (block_index, TRUE, NULL))
-                       ++num_major_sections_freed_in_sweep;
+       for (block_index = allocated_blocks.next_slot; block_index-- > 0;) {
+               ensure_block_is_checked_for_sweeping (block_index, TRUE, NULL);
        }
 
        while (!try_set_sweep_state (SWEEP_STATE_COMPACTING, SWEEP_STATE_SWEEPING)) {
@@ -1681,8 +1675,6 @@ major_sweep (void)
 
        sweep_start ();
 
-       SGEN_ASSERT (0, num_major_sections == allocated_blocks.next_slot, "We don't know how many blocks we have?");
-
        num_major_sections_before_sweep = num_major_sections;
        num_major_sections_freed_in_sweep = 0;
 
@@ -2547,7 +2539,7 @@ post_param_init (SgenMajorCollector *collector)
 }
 
 static void
-sgen_marksweep_init_internal (SgenMajorCollector *collector, gboolean is_concurrent)
+sgen_marksweep_init_internal (SgenMajorCollector *collector, gboolean is_concurrent, gboolean is_parallel)
 {
        int i;
 
@@ -2594,6 +2586,7 @@ sgen_marksweep_init_internal (SgenMajorCollector *collector, gboolean is_concurr
 
        concurrent_mark = is_concurrent;
        collector->is_concurrent = is_concurrent;
+       collector->is_parallel = is_parallel;
        collector->needs_thread_pool = is_concurrent || concurrent_sweep;
        collector->get_and_reset_num_major_objects_marked = major_get_and_reset_num_major_objects_marked;
        collector->supports_cardtable = TRUE;
@@ -2655,6 +2648,12 @@ sgen_marksweep_init_internal (SgenMajorCollector *collector, gboolean is_concurr
                collector->major_ops_concurrent_finish.scan_vtype = major_scan_vtype_with_evacuation;
                collector->major_ops_concurrent_finish.scan_ptr_field = major_scan_ptr_field_with_evacuation;
                collector->major_ops_concurrent_finish.drain_gray_stack = drain_gray_stack;
+
+               if (is_parallel) {
+                       /* FIXME use parallel obj ops */
+                       collector->major_ops_conc_par_start = collector->major_ops_concurrent_start;
+                       collector->major_ops_conc_par_finish = collector->major_ops_concurrent_finish;
+               }
        }
 
 #ifdef HEAVY_STATISTICS
@@ -2688,13 +2687,19 @@ sgen_marksweep_init_internal (SgenMajorCollector *collector, gboolean is_concurr
 void
 sgen_marksweep_init (SgenMajorCollector *collector)
 {
-       sgen_marksweep_init_internal (collector, FALSE);
+       sgen_marksweep_init_internal (collector, FALSE, FALSE);
 }
 
 void
 sgen_marksweep_conc_init (SgenMajorCollector *collector)
 {
-       sgen_marksweep_init_internal (collector, TRUE);
+       sgen_marksweep_init_internal (collector, TRUE, FALSE);
+}
+
+void
+sgen_marksweep_conc_par_init (SgenMajorCollector *collector)
+{
+       sgen_marksweep_init_internal (collector, TRUE, TRUE);
 }
 
 #endif