]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.garbage] runtime: Code to implement write barriers
authorRick Hudson <rlh@golang.org>
Mon, 10 Nov 2014 18:42:34 +0000 (13:42 -0500)
committerRuss Cox <rsc@golang.org>
Mon, 10 Nov 2014 18:42:34 +0000 (13:42 -0500)
To turn concurrent gc on alter the if false in func gogc
currently at line 489 in malloc.go

LGTM=rsc
R=rsc
CC=golang-codereviews, rlh
https://golang.org/cl/172190043

src/runtime/malloc.go
src/runtime/mgc0.c
src/runtime/mgc0.go
src/runtime/runtime.h
src/runtime/stubs.go

index 274bae9a3628e4ab7e810354fcfceef97aabb8a0..a18e77421e886b0a243a30871624c8f0e9408797 100644 (file)
@@ -486,16 +486,17 @@ func gogc(force int32) {
 
        onM(stoptheworld)
        onM(finishsweep_m) // finish sweep before we start concurrent scan.
-       onM(starttheworld)
-
-       // Do a concurrent heap scan before we stop the world.
-       onM(gcscan_m)
-       onM(gcinstallmarkwb_m)
-       onM(stoptheworld)
-       //      onM(starttheworld)
-       // mark from roots scanned in gcscan_m. startthework when write barrier works
-       onM(gcmark_m)
-       //      onM(stoptheworld)
+       if false {         // To turn on concurrent scan and mark set to true...
+               onM(starttheworld)
+               // Do a concurrent heap scan before we stop the world.
+               onM(gcscan_m)
+               onM(stoptheworld)
+               onM(gcinstallmarkwb_m)
+               onM(starttheworld)
+               onM(gcmark_m)
+               onM(stoptheworld)
+               onM(gcinstalloffwb_m)
+       }
        if mp != acquirem() {
                gothrow("gogc: rescheduled")
        }
index 3ebaf005f5b7c36548fc545fbf41215c15355960..5300f554bfd4a24e96667c80ff34d76f46611826 100644 (file)
@@ -1061,13 +1061,34 @@ shade(byte *b)
 //
 // Shade indicates that it has seen a white pointer by adding the referent
 // to wbuf.
+// slot is the destination (dst) in go code
+// ptr is the value that goes into the slot (src) in the go code
 void
-runtime·markwb(void **slot, void *ptr)
+runtime·gcmarkwb_m()
 {
-       // initial nil check avoids some needlesss loads
-       if(ptr != nil && inheap(ptr) && shaded((void*)slot))
-               shade(ptr);
+       byte **slot, *ptr;
+       slot = (byte**)g->m->scalararg[0];
+       ptr = (byte*)g->m->scalararg[1];
+
        *slot = ptr;
+       switch(runtime·gcphase) {
+       default:
+               runtime·throw("gcphasework in bad gcphase");
+       case GCoff:
+       case GCquiesce:
+       case GCstw:
+       case GCsweep:
+       case GCscan:
+               break;
+       case GCmark:
+               if(ptr != nil && inheap(ptr) && shaded((byte*)slot))
+                       shade(ptr);
+               break;
+       case GCmarktermination:
+               if(ptr != nil && inheap(ptr) && shaded((byte*)slot))
+                       shade(ptr);
+               break;
+       }
 }
 
 // The gp has been moved to a GC safepoint. GC phase specific
@@ -1945,7 +1966,7 @@ runtime·gcmark_m(void)
        scanblock(nil, 0, nil);
 }
 
-// For now this must be followed by a stoptheworld and a starttheworld to ensure
+// For now this must be bracketed with a stoptheworld and a starttheworld to ensure
 // all go routines see the new barrier.
 void
 runtime·gcinstallmarkwb_m(void)
@@ -1953,6 +1974,14 @@ runtime·gcinstallmarkwb_m(void)
        runtime·gcphase = GCmark;
 }
 
+// For now this must be bracketed with a stoptheworld and a starttheworld to ensure
+// all go routines see the new barrier.
+void
+runtime·gcinstalloffwb_m(void)
+{
+       runtime·gcphase = GCoff;
+}
+
 static void
 gc(struct gc_args *args)
 {
index 22e88494a0d8bb78aa67f40d5fe88ac91dc56a2f..ce5c290efa50e42b810f9c3d9cc3146b46429214 100644 (file)
@@ -95,7 +95,24 @@ func writebarrierptr(dst *uintptr, src uintptr) {
        if src != 0 && (src < _PageSize || src == _PoisonGC || src == _PoisonStack) {
                onM(func() { gothrow("bad pointer in write barrier") })
        }
-       *dst = src
+
+       mp := acquirem()
+       if mp.inwb {
+               *dst = src
+               releasem(mp)
+               return
+       }
+       mp.inwb = true
+       oldscalar0 := mp.scalararg[0]
+       oldscalar1 := mp.scalararg[1]
+       mp.scalararg[0] = uintptr(unsafe.Pointer(dst))
+       mp.scalararg[1] = src
+       onM_signalok(gcmarkwb_m)
+       mp.scalararg[0] = oldscalar0
+       mp.scalararg[1] = oldscalar1
+       mp.inwb = false
+       releasem(mp)
+       //      *dst = src is done inside of the write barrier.
 }
 
 //go:nosplit
index ee86f2d1765af1cb778fb5d03fdd083bda627775..a0f1acc05f981dd080c136251622585d50c430eb 100644 (file)
@@ -345,6 +345,7 @@ struct      M
        int32   helpgc;
        bool    spinning;       // M is out of work and is actively looking for work
        bool    blocked;        // M is blocked on a Note
+       bool    inwb;           // M is executing a write barrier
        int8    printlock;
        uint32  fastrand;
        uint64  ncgocall;       // number of cgo calls in total
index 68f464f5717b6989a6dcd42e3220936fbce9874b..852f4ddbb65a21b0ae4f28544bc210dda75ed2be 100644 (file)
@@ -112,7 +112,9 @@ func gccheckmark_m()
 func gccheckmarkenable_m()
 func gccheckmarkdisable_m()
 func gcinstallmarkwb_m()
+func gcinstalloffwb_m()
 func gcmarknewobject_m()
+func gcmarkwb_m()
 func finishsweep_m()
 func scavenge_m()
 func setFinalizer_m()