summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRick Hudson <rlh@golang.org>2014-11-10 14:32:02 -0500
committerRick Hudson <rlh@golang.org>2014-11-10 14:32:02 -0500
commit11c9da27d8b3d09835a611edea424885af1ec650 (patch)
treec761631e9c9f788cf3684ebbf1f4a1c8533d5792
parentcb223591339d2e03283e21144057b30d5e9667dd (diff)
downloadgo-11c9da27d8b3d09835a611edea424885af1ec650.tar.gz
[dev.garbage] runtime: Coarsen the write barrier to always grey the destination.
LGTM=rsc R=rsc CC=golang-codereviews https://codereview.appspot.com/174820043
-rw-r--r--src/runtime/mgc0.c38
1 files changed, 33 insertions, 5 deletions
diff --git a/src/runtime/mgc0.c b/src/runtime/mgc0.c
index 5300f554b..3f6cce5c0 100644
--- a/src/runtime/mgc0.c
+++ b/src/runtime/mgc0.c
@@ -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;
}