runtime: use timer for GC control revise rather than timeout

Currently, we use a note sleep with a timeout in a loop in func gc to
periodically revise the GC control variables. Replace this with a
fully blocking note sleep and use a periodic timer to trigger the
revise instead. This is a step toward replacing the note sleep in func
gc.

Change-Id: I2d562f6b9b2e5f0c28e9a54227e2c0f8a2603f63
Reviewed-on: https://go-review.googlesource.com/9290
Reviewed-by: Rick Hudson <rlh@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
diff --git a/src/runtime/mgc.go b/src/runtime/mgc.go
index f3e5a67..3bc5689 100644
--- a/src/runtime/mgc.go
+++ b/src/runtime/mgc.go
@@ -298,6 +298,10 @@
 	// at the end of of each cycle.
 	triggerRatio float64
 
+	// reviseTimer is a timer that triggers periodic revision of
+	// control variables during the cycle.
+	reviseTimer timer
+
 	_ [_CacheLineSize]byte
 
 	// fractionalMarkWorkersNeeded is the number of fractional
@@ -344,10 +348,6 @@
 		c.fractionalMarkWorkersNeeded = 0
 	}
 
-	// Compute initial values for controls that are updated
-	// throughout the cycle.
-	c.revise()
-
 	// Clear per-P state
 	for _, p := range &allp {
 		if p == nil {
@@ -356,7 +356,17 @@
 		p.gcAssistTime = 0
 	}
 
-	return
+	// Compute initial values for controls that are updated
+	// throughout the cycle.
+	c.revise()
+
+	// Set up a timer to revise periodically
+	c.reviseTimer.f = func(interface{}, uintptr) {
+		gcController.revise()
+	}
+	c.reviseTimer.period = 10 * 1000 * 1000
+	c.reviseTimer.when = nanotime() + c.reviseTimer.period
+	addtimer(&c.reviseTimer)
 }
 
 // revise updates the assist ratio during the GC cycle to account for
@@ -408,6 +418,9 @@
 	// EWMA weight given to this cycle's scan work ratio.
 	const workRatioWeight = 0.75
 
+	// Stop the revise timer
+	deltimer(&c.reviseTimer)
+
 	// Compute next cycle trigger ratio. First, this computes the
 	// "error" for this cycle; that is, how far off the trigger
 	// was from what it should have been, accounting for both heap
@@ -768,9 +781,7 @@
 		if debug.gctrace > 0 {
 			tMark = nanotime()
 		}
-		for !notetsleepg(&work.bgMarkNote, 10*1000*1000) {
-			gcController.revise()
-		}
+		notetsleepg(&work.bgMarkNote, -1)
 		noteclear(&work.bgMarkNote)
 
 		// Begin mark termination.