Commit fed5428c authored by Dmitriy Vyukov's avatar Dmitriy Vyukov

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
parent 8d321625
...@@ -248,6 +248,7 @@ static int32 fingwait; ...@@ -248,6 +248,7 @@ static int32 fingwait;
static Lock gclock; static Lock gclock;
static void runfinq(void); static void runfinq(void);
static void wakefing(void);
static void bgsweep(void); static void bgsweep(void);
static Workbuf* getempty(Workbuf*); static Workbuf* getempty(Workbuf*);
static Workbuf* getfull(Workbuf*); static Workbuf* getfull(Workbuf*);
...@@ -1880,6 +1881,7 @@ static struct ...@@ -1880,6 +1881,7 @@ static struct
{ {
G* g; G* g;
bool parked; bool parked;
uint32 lastsweepgen;
MSpan** spans; MSpan** spans;
uint32 nspan; uint32 nspan;
...@@ -1894,18 +1896,18 @@ bgsweep(void) ...@@ -1894,18 +1896,18 @@ bgsweep(void)
for(;;) { for(;;) {
while(runtime·sweepone() != -1) { while(runtime·sweepone() != -1) {
gcstats.nbgsweep++; 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(); runtime·gosched();
} }
// kick off goroutine to run queued finalizers
wakefing();
runtime·lock(&gclock); 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) { if(!runtime·mheap.sweepdone) {
// It's possible if GC has happened between sweepone has // It's possible if GC has happened between sweepone has
// returned -1 and gclock lock. // returned -1 and gclock lock.
...@@ -2257,17 +2259,8 @@ runtime·gc(int32 force) ...@@ -2257,17 +2259,8 @@ runtime·gc(int32 force)
// now that gc is done, kick off finalizer thread if needed // now that gc is done, kick off finalizer thread if needed
if(!ConcurrentSweep) { if(!ConcurrentSweep) {
if(finq != nil) { // kick off goroutine to run queued finalizers
runtime·lock(&gclock); wakefing();
// 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);
}
// give the queued finalizers, if any, a chance to run // give the queued finalizers, if any, a chance to run
runtime·gosched(); runtime·gosched();
} }
...@@ -2621,6 +2614,22 @@ runfinq(void) ...@@ -2621,6 +2614,22 @@ runfinq(void)
} }
} }
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 void
runtime·marknogc(void *v) runtime·marknogc(void *v)
{ {
......
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