Commit d3d60975 authored by Rick Hudson's avatar Rick Hudson Committed by Russ Cox

[dev.garbage] runtime: Code to implement write barriers

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
parent d8ee1c5a
...@@ -486,16 +486,17 @@ func gogc(force int32) { ...@@ -486,16 +486,17 @@ func gogc(force int32) {
onM(stoptheworld) onM(stoptheworld)
onM(finishsweep_m) // finish sweep before we start concurrent scan. onM(finishsweep_m) // finish sweep before we start concurrent scan.
if false { // To turn on concurrent scan and mark set to true...
onM(starttheworld) onM(starttheworld)
// Do a concurrent heap scan before we stop the world. // Do a concurrent heap scan before we stop the world.
onM(gcscan_m) onM(gcscan_m)
onM(gcinstallmarkwb_m)
onM(stoptheworld) onM(stoptheworld)
// onM(starttheworld) onM(gcinstallmarkwb_m)
// mark from roots scanned in gcscan_m. startthework when write barrier works onM(starttheworld)
onM(gcmark_m) onM(gcmark_m)
// onM(stoptheworld) onM(stoptheworld)
onM(gcinstalloffwb_m)
}
if mp != acquirem() { if mp != acquirem() {
gothrow("gogc: rescheduled") gothrow("gogc: rescheduled")
} }
......
...@@ -1061,13 +1061,34 @@ shade(byte *b) ...@@ -1061,13 +1061,34 @@ shade(byte *b)
// //
// Shade indicates that it has seen a white pointer by adding the referent // Shade indicates that it has seen a white pointer by adding the referent
// to wbuf. // 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 void
runtime·markwb(void **slot, void *ptr) runtime·gcmarkwb_m()
{ {
// initial nil check avoids some needlesss loads byte **slot, *ptr;
if(ptr != nil && inheap(ptr) && shaded((void*)slot)) slot = (byte**)g->m->scalararg[0];
shade(ptr); ptr = (byte*)g->m->scalararg[1];
*slot = ptr; *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 // The gp has been moved to a GC safepoint. GC phase specific
...@@ -1945,7 +1966,7 @@ runtime·gcmark_m(void) ...@@ -1945,7 +1966,7 @@ runtime·gcmark_m(void)
scanblock(nil, 0, nil); 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. // all go routines see the new barrier.
void void
runtime·gcinstallmarkwb_m(void) runtime·gcinstallmarkwb_m(void)
...@@ -1953,6 +1974,14 @@ runtime·gcinstallmarkwb_m(void) ...@@ -1953,6 +1974,14 @@ runtime·gcinstallmarkwb_m(void)
runtime·gcphase = GCmark; 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 static void
gc(struct gc_args *args) gc(struct gc_args *args)
{ {
......
...@@ -95,7 +95,24 @@ func writebarrierptr(dst *uintptr, src uintptr) { ...@@ -95,7 +95,24 @@ func writebarrierptr(dst *uintptr, src uintptr) {
if src != 0 && (src < _PageSize || src == _PoisonGC || src == _PoisonStack) { if src != 0 && (src < _PageSize || src == _PoisonGC || src == _PoisonStack) {
onM(func() { gothrow("bad pointer in write barrier") }) onM(func() { gothrow("bad pointer in write barrier") })
} }
mp := acquirem()
if mp.inwb {
*dst = src *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 //go:nosplit
......
...@@ -345,6 +345,7 @@ struct M ...@@ -345,6 +345,7 @@ struct M
int32 helpgc; int32 helpgc;
bool spinning; // M is out of work and is actively looking for work bool spinning; // M is out of work and is actively looking for work
bool blocked; // M is blocked on a Note bool blocked; // M is blocked on a Note
bool inwb; // M is executing a write barrier
int8 printlock; int8 printlock;
uint32 fastrand; uint32 fastrand;
uint64 ncgocall; // number of cgo calls in total uint64 ncgocall; // number of cgo calls in total
......
...@@ -112,7 +112,9 @@ func gccheckmark_m() ...@@ -112,7 +112,9 @@ func gccheckmark_m()
func gccheckmarkenable_m() func gccheckmarkenable_m()
func gccheckmarkdisable_m() func gccheckmarkdisable_m()
func gcinstallmarkwb_m() func gcinstallmarkwb_m()
func gcinstalloffwb_m()
func gcmarknewobject_m() func gcmarknewobject_m()
func gcmarkwb_m()
func finishsweep_m() func finishsweep_m()
func scavenge_m() func scavenge_m()
func setFinalizer_m() func setFinalizer_m()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment