runtime: fix another race in bgsweep
It's possible that bgsweep constantly does not catch up for some reason,
in this case runfinq was not woken at all.

R=rsc
CC=golang-codereviews
https://golang.org/cl/75940043
diff --git a/src/pkg/runtime/mgc0.c b/src/pkg/runtime/mgc0.c
index b7f6adf..a726fb4 100644
--- a/src/pkg/runtime/mgc0.c
+++ b/src/pkg/runtime/mgc0.c
@@ -248,6 +248,7 @@
 static Lock	gclock;
 
 static void	runfinq(void);
+static void	wakefing(void);
 static void	bgsweep(void);
 static Workbuf* getempty(Workbuf*);
 static Workbuf* getfull(Workbuf*);
@@ -1880,6 +1881,7 @@
 {
 	G*	g;
 	bool	parked;
+	uint32	lastsweepgen;
 
 	MSpan**	spans;
 	uint32	nspan;
@@ -1894,18 +1896,18 @@
 	for(;;) {
 		while(runtime·sweepone() != -1) {
 			gcstats.nbgsweep++;
+			if(sweep.lastsweepgen != runtime·mheap.sweepgen) {
+				// If bgsweep does not catch up for any reason
+				// (does not finish before next GC),
+				// we still need to kick off runfinq at least once per GC.
+				sweep.lastsweepgen = runtime·mheap.sweepgen;
+				wakefing();
+			}
 			runtime·gosched();
 		}
+		// kick off goroutine to run queued finalizers
+		wakefing();
 		runtime·lock(&gclock);
-		if(finq != nil) {
-			// kick off or wake up goroutine to run queued finalizers
-			if(fing == nil)
-				fing = runtime·newproc1(&runfinqv, nil, 0, 0, runtime·gc);
-			else if(fingwait) {
-				fingwait = 0;
-				runtime·ready(fing);
-			}
-		}
 		if(!runtime·mheap.sweepdone) {
 			// It's possible if GC has happened between sweepone has
 			// returned -1 and gclock lock.
@@ -2257,17 +2259,8 @@
 
 	// now that gc is done, kick off finalizer thread if needed
 	if(!ConcurrentSweep) {
-		if(finq != nil) {
-			runtime·lock(&gclock);
-			// kick off or wake up goroutine to run queued finalizers
-			if(fing == nil)
-				fing = runtime·newproc1(&runfinqv, nil, 0, 0, runtime·gc);
-			else if(fingwait) {
-				fingwait = 0;
-				runtime·ready(fing);
-			}
-			runtime·unlock(&gclock);
-		}
+		// kick off goroutine to run queued finalizers
+		wakefing();
 		// give the queued finalizers, if any, a chance to run
 		runtime·gosched();
 	}
@@ -2621,6 +2614,22 @@
 	}
 }
 
+static void
+wakefing(void)
+{
+	if(finq == nil)
+		return;
+	runtime·lock(&gclock);
+	// kick off or wake up goroutine to run queued finalizers
+	if(fing == nil)
+		fing = runtime·newproc1(&runfinqv, nil, 0, 0, runtime·gc);
+	else if(fingwait) {
+		fingwait = 0;
+		runtime·ready(fing);
+	}
+	runtime·unlock(&gclock);
+}
+
 void
 runtime·marknogc(void *v)
 {