[sgen] Run the scan pinned object job concurrently with minors
authorVlad Brezae <brezaevlad@gmail.com>
Tue, 20 Jun 2017 12:22:39 +0000 (15:22 +0300)
committerVlad Brezae <brezaevlad@gmail.com>
Fri, 23 Jun 2017 17:46:09 +0000 (20:46 +0300)
Concurrent mark doesn't normally scan objects in the nursery since they can be moved. At the end of the concurrent mark, we were locking over the entire gc pause in order to make sure that the we can scan the latest pinned object list (aka none of those objects can be moved). Lock only over the pinning phase of the collection, since it is enough.

mono/sgen/sgen-gc.c
mono/sgen/sgen-pinning.c
mono/sgen/sgen-pinning.h

index 2f761cc8a13dd6b310d770f6dd54d17a87614503..b7951955ca54c78410c75ab05c56a77a235a5b0b 100644 (file)
@@ -1705,6 +1705,8 @@ collect_nursery (const char *reason, gboolean is_overflow, SgenGrayQueue *unpin_
 
        /* pin from pinned handles */
        sgen_init_pinning ();
+       if (concurrent_collection_in_progress)
+               sgen_init_pinning_for_conc ();
        sgen_client_binary_protocol_mark_start (GENERATION_NURSERY);
        pin_from_roots (nursery_section->data, nursery_section->end_data, ctx);
        /* pin cemented objects */
@@ -1715,6 +1717,8 @@ collect_nursery (const char *reason, gboolean is_overflow, SgenGrayQueue *unpin_
 
        pin_objects_in_nursery (FALSE, ctx);
        sgen_pinning_trim_queue_to_section (nursery_section);
+       if (concurrent_collection_in_progress)
+               sgen_finish_pinning_for_conc ();
 
        if (remset_consistency_checks)
                sgen_check_remset_consistency ();
@@ -1904,6 +1908,8 @@ major_copy_or_mark_from_roots (SgenGrayQueue *gc_thread_gray_queue, size_t *old_
 
        TV_GETTIME (atv);
        sgen_init_pinning ();
+       if (mode == COPY_OR_MARK_FROM_ROOTS_START_CONCURRENT)
+               sgen_init_pinning_for_conc ();
        SGEN_LOG (6, "Collecting pinned addresses");
        pin_from_roots ((void*)lowest_heap_address, (void*)highest_heap_address, ctx);
        if (mode == COPY_OR_MARK_FROM_ROOTS_FINISH_CONCURRENT) {
@@ -1974,6 +1980,9 @@ major_copy_or_mark_from_roots (SgenGrayQueue *gc_thread_gray_queue, size_t *old_
        SGEN_LOG (2, "Finding pinned pointers: %zd in %lld usecs", sgen_get_pinned_count (), (long long)TV_ELAPSED (atv, btv));
        SGEN_LOG (4, "Start scan with %zd pinned objects", sgen_get_pinned_count ());
 
+       if (mode == COPY_OR_MARK_FROM_ROOTS_START_CONCURRENT)
+               sgen_finish_pinning_for_conc ();
+
        major_collector.init_to_space ();
 
        SGEN_ASSERT (0, sgen_workers_all_done (), "Why are the workers not done when we start or finish a major collection?");
index 904688c2ae81f628eb8b52d37da7ddfc03564927..0e711d1aa15a265b4fa466c00a595c884568a9ef 100644 (file)
@@ -41,9 +41,14 @@ sgen_pinning_init (void)
 void
 sgen_init_pinning (void)
 {
-       mono_os_mutex_lock (&pin_queue_mutex);
        memset (pin_hash_filter, 0, sizeof (pin_hash_filter));
        pin_queue.mem_type = INTERNAL_MEM_PIN_QUEUE;
+}
+
+void
+sgen_init_pinning_for_conc (void)
+{
+       mono_os_mutex_lock (&pin_queue_mutex);
        sgen_pointer_queue_clear (&pin_queue_objs);
 }
 
@@ -52,6 +57,11 @@ sgen_finish_pinning (void)
 {
        last_num_pinned = pin_queue.next_slot;
        sgen_pointer_queue_clear (&pin_queue);
+}
+
+void
+sgen_finish_pinning_for_conc (void)
+{
        mono_os_mutex_unlock (&pin_queue_mutex);
 }
 
index cdd673f29b5b2ca2df1613f1911bc9cd456bfb1b..797e12b2614b29be157f2533f98ec03a96ef59f1 100644 (file)
@@ -23,6 +23,8 @@ void sgen_pinning_init (void);
 void sgen_pin_stage_ptr (void *ptr);
 void sgen_optimize_pin_queue (void);
 void sgen_init_pinning (void);
+void sgen_init_pinning_for_conc (void);
+void sgen_finish_pinning_for_conc (void);
 void sgen_finish_pinning (void);
 void sgen_pinning_register_pinned_in_nursery (GCObject *obj);
 void sgen_scan_pin_queue_objects (ScanCopyContext ctx);