Bgc suspension fixes (dotnet/coreclr#27729)
authorPeter Sollich <petersol@microsoft.com>
Wed, 13 Nov 2019 23:24:20 +0000 (00:24 +0100)
committerSergiy Kuryata <sergeyk@microsoft.com>
Wed, 13 Nov 2019 23:24:20 +0000 (15:24 -0800)
* Changes to set gen0 bricks always. This reduces the time spent in find_first_object when finding the start of objects for marking interior pointers.

* Revert "Changes to set gen0 bricks always. This reduces the time spent in find_first_object when finding the start of objects for marking interior pointers."

This reverts commit dotnet/coreclr@9d53ff910ceb5482c67350a88e6687b8f94d5634.

* Two fixes to speed up suspension for foreground GCs while background GC is in progress:

- In background_mark_simple1, check g_fSuspensionPending and if it is set, save the state of the work and restart the loop - this will call allow_fgc() and thus allow a foreground GC to take place.

- In revisit_written_page, call allow_fgc() at the end - this allow a foreground GC to happen whenever we are done with revisiting a written page.

* Addressed code review feedback - use counter instead of testing g_fSuspensionPending directly.

Commit migrated from https://github.com/dotnet/coreclr/commit/a7678f5d8e14ad0edc8d996ae4048079c7b2d575

src/coreclr/src/gc/gc.cpp

index 269f99b..4105d7e 100644 (file)
@@ -19882,7 +19882,8 @@ void gc_heap::background_mark_simple1 (uint8_t* oo THREAD_NUMBER_DCL)
                     *(place) = start;
                     *(background_mark_stack_tos++) = (uint8_t*)((size_t)oo | 1);
 
-                    int i = num_partial_refs;
+                    int num_pushed_refs = num_partial_refs;
+                    int num_processed_refs = num_pushed_refs * 16;
 
                     go_through_object (method_table(oo), oo, s, ppslot,
                                        start, use_start, (oo + s),
@@ -19900,7 +19901,7 @@ void gc_heap::background_mark_simple1 (uint8_t* oo THREAD_NUMBER_DCL)
                             if (contain_pointers_or_collectible (o))
                             {
                                 *(background_mark_stack_tos++) = o;
-                                if (--i == 0)
+                                if (--num_pushed_refs == 0)
                                 {
                                     //update the start
                                     *place = (uint8_t*)(ppslot+1);
@@ -19909,13 +19910,19 @@ void gc_heap::background_mark_simple1 (uint8_t* oo THREAD_NUMBER_DCL)
 
                             }
                         }
+                        if (--num_processed_refs == 0)
+                        {
+                            // give foreground GC a chance to run
+                            *place = (uint8_t*)(ppslot + 1);
+                            goto more_to_do;
+                        }
 
-                    }
+                        }
                         );
                     //we are finished with this object
                     *place = 0;
                     *(place+1) = 0;
-
+                
                 more_to_do:;
                 }
                 else
@@ -27971,9 +27978,6 @@ void gc_heap::revisit_written_page (uint8_t* page,
             }
             else if (
                 concurrent_p &&
-#ifndef FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP // see comment below
-                large_objects_p &&
-#endif // !FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP
                 ((CObjectHeader*)o)->IsFree() &&
                 (next_o > min (high_address, page + WRITE_WATCH_UNIT_SIZE)))
             {
@@ -28022,6 +28026,11 @@ end_limit:
 
     dprintf (3,("Last object: %Ix", (size_t)last_object));
     last_page = align_write_watch_lower_page (o);
+
+    if (concurrent_p)
+    {
+        allow_fgc();
+    }
 }
 
 // When reset_only_p is TRUE, we should only reset pages that are in range