]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.garbage] runtime: Coarsen the write barrier to always grey the destination.
authorRick Hudson <rlh@golang.org>
Mon, 10 Nov 2014 19:32:02 +0000 (14:32 -0500)
committerRick Hudson <rlh@golang.org>
Mon, 10 Nov 2014 19:32:02 +0000 (14:32 -0500)
LGTM=rsc
R=rsc
CC=golang-codereviews
https://golang.org/cl/174820043

src/runtime/mgc0.c

index 5300f554bfd4a24e96667c80ff34d76f46611826..3f6cce5c0f5ec3d3f7f71e9809d2548a1a6be15e 100644 (file)
@@ -1056,13 +1056,41 @@ shade(byte *b)
        return;
 }
 
-// This is the Dijkstra barrier coarsened to shade grey to white whereas
-// the original Dijkstra barrier only shaded black to white.
+// This is the Dijkstra barrier coarsened to always shade the ptr (dst) object.
+// The original Dijkstra barrier only shaded ptrs being placed in black slots.
 //
 // Shade indicates that it has seen a white pointer by adding the referent
-// to wbuf.
+// to wbuf as well as marking it.
+//
 // slot is the destination (dst) in go code
 // ptr is the value that goes into the slot (src) in the go code
+//
+// Dijkstra pointed out that maintaining the no black to white
+// pointers means that white to white pointers not need 
+// to be noted by the write barrier. Furthermore if either 
+// white object dies before it is reached by the 
+// GC then the object can be collected during this GC cycle 
+// instead of waiting for the next cycle. Unfortunately the cost of 
+// ensure that the object holding the slot doesn't concurrently
+// change to black without the mutator noticing seems prohibitive.
+//
+// Consider the following example where the mutator writes into 
+// a slot and then loads the slot's mark bit while the GC thread 
+// writes to the slot's mark bit and then as part of scanning reads 
+// the slot.
+// 
+// Initially both [slot] and [slotmark] are 0 (nil)
+// Mutator thread          GC thread
+// st [slot], ptr          st [slotmark], 1
+// 
+// ld r1, [slotmark]       ld r2, [slot]
+//
+// This is a classic example of independent reads of independent writes,
+// aka IRIW. The question is if r1==r2==0 is allowed and for most HW the 
+// answer is yes without inserting a memory barriers between the st and the ld. 
+// These barriers are expensive so we have decided that we will 
+// always grey the ptr object regardless of the slot's color.
+// 
 void
 runtime·gcmarkwb_m()
 {
@@ -1081,11 +1109,11 @@ runtime·gcmarkwb_m()
        case GCscan:
                break;
        case GCmark:
-               if(ptr != nil && inheap(ptr) && shaded((byte*)slot))
+               if(ptr != nil && inheap(ptr))
                        shade(ptr);
                break;
        case GCmarktermination:
-               if(ptr != nil && inheap(ptr) && shaded((byte*)slot))
+               if(ptr != nil && inheap(ptr))
                        shade(ptr);
                break;
        }