mirror of
https://github.com/golang/go
synced 2024-11-26 10:28:19 -07:00
runtime: properly synchronize GC and finalizer goroutine
This is needed for preemptive scheduler, because the goroutine can be preempted at surprising points. R=golang-dev, iant CC=golang-dev https://golang.org/cl/9376043
This commit is contained in:
parent
34c67eb24e
commit
72c4ee1a9d
@ -2030,18 +2030,6 @@ gc(struct gc_args *args)
|
|||||||
mstats.next_gc = mstats.heap_alloc+mstats.heap_alloc*gcpercent/100;
|
mstats.next_gc = mstats.heap_alloc+mstats.heap_alloc*gcpercent/100;
|
||||||
m->gcing = 0;
|
m->gcing = 0;
|
||||||
|
|
||||||
if(finq != nil) {
|
|
||||||
m->locks++; // disable gc during the mallocs in newproc
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
m->locks--;
|
|
||||||
}
|
|
||||||
|
|
||||||
heap1 = mstats.heap_alloc;
|
heap1 = mstats.heap_alloc;
|
||||||
obj1 = mstats.nmalloc - mstats.nfree;
|
obj1 = mstats.nmalloc - mstats.nfree;
|
||||||
|
|
||||||
@ -2089,9 +2077,19 @@ gc(struct gc_args *args)
|
|||||||
runtime·semrelease(&runtime·worldsema);
|
runtime·semrelease(&runtime·worldsema);
|
||||||
runtime·starttheworld();
|
runtime·starttheworld();
|
||||||
|
|
||||||
// give the queued finalizers, if any, a chance to run
|
if(finq != nil) {
|
||||||
if(finq != nil)
|
runtime·lock(&finlock);
|
||||||
|
// 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(&finlock);
|
||||||
|
// give the queued finalizers, if any, a chance to run
|
||||||
runtime·gosched();
|
runtime·gosched();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -2176,19 +2174,15 @@ runfinq(void)
|
|||||||
frame = nil;
|
frame = nil;
|
||||||
framecap = 0;
|
framecap = 0;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
// There's no need for a lock in this section
|
runtime·lock(&finlock);
|
||||||
// because it only conflicts with the garbage
|
|
||||||
// collector, and the garbage collector only
|
|
||||||
// runs when everyone else is stopped, and
|
|
||||||
// runfinq only stops at the gosched() or
|
|
||||||
// during the calls in the for loop.
|
|
||||||
fb = finq;
|
fb = finq;
|
||||||
finq = nil;
|
finq = nil;
|
||||||
if(fb == nil) {
|
if(fb == nil) {
|
||||||
fingwait = 1;
|
fingwait = 1;
|
||||||
runtime·park(nil, nil, "finalizer wait");
|
runtime·park(runtime·unlock, &finlock, "finalizer wait");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
runtime·unlock(&finlock);
|
||||||
if(raceenabled)
|
if(raceenabled)
|
||||||
runtime·racefingo();
|
runtime·racefingo();
|
||||||
for(; fb; fb=next) {
|
for(; fb; fb=next) {
|
||||||
|
Loading…
Reference in New Issue
Block a user