Update to go1.23.4
This commit is contained in:
@@ -190,6 +190,7 @@ func gcinit() {
|
||||
work.markDoneSema = 1
|
||||
lockInit(&work.sweepWaiters.lock, lockRankSweepWaiters)
|
||||
lockInit(&work.assistQueue.lock, lockRankAssistQueue)
|
||||
lockInit(&work.strongFromWeak.lock, lockRankStrongFromWeakQueue)
|
||||
lockInit(&work.wbufSpans.lock, lockRankWbufSpans)
|
||||
}
|
||||
|
||||
@@ -418,6 +419,26 @@ type workType struct {
|
||||
list gList
|
||||
}
|
||||
|
||||
// strongFromWeak controls how the GC interacts with weak->strong
|
||||
// pointer conversions.
|
||||
strongFromWeak struct {
|
||||
// block is a flag set during mark termination that prevents
|
||||
// new weak->strong conversions from executing by blocking the
|
||||
// goroutine and enqueuing it onto q.
|
||||
//
|
||||
// Mutated only by one goroutine at a time in gcMarkDone,
|
||||
// with globally-synchronizing events like forEachP and
|
||||
// stopTheWorld.
|
||||
block bool
|
||||
|
||||
// q is a queue of goroutines that attempted to perform a
|
||||
// weak->strong conversion during mark termination.
|
||||
//
|
||||
// Protected by lock.
|
||||
lock mutex
|
||||
q gQueue
|
||||
}
|
||||
|
||||
// cycles is the number of completed GC cycles, where a GC
|
||||
// cycle is sweep termination, mark, mark termination, and
|
||||
// sweep. This differs from memstats.numgc, which is
|
||||
@@ -800,6 +821,19 @@ func gcStart(trigger gcTrigger) {
|
||||
// This is protected by markDoneSema.
|
||||
var gcMarkDoneFlushed uint32
|
||||
|
||||
// gcDebugMarkDone contains fields used to debug/test mark termination.
|
||||
var gcDebugMarkDone struct {
|
||||
// spinAfterRaggedBarrier forces gcMarkDone to spin after it executes
|
||||
// the ragged barrier.
|
||||
spinAfterRaggedBarrier atomic.Bool
|
||||
|
||||
// restartedDueTo27993 indicates that we restarted mark termination
|
||||
// due to the bug described in issue #27993.
|
||||
//
|
||||
// Protected by worldsema.
|
||||
restartedDueTo27993 bool
|
||||
}
|
||||
|
||||
// gcMarkDone transitions the GC from mark to mark termination if all
|
||||
// reachable objects have been marked (that is, there are no grey
|
||||
// objects and can be no more in the future). Otherwise, it flushes
|
||||
@@ -842,6 +876,10 @@ top:
|
||||
// stop the world later, so acquire worldsema now.
|
||||
semacquire(&worldsema)
|
||||
|
||||
// Prevent weak->strong conversions from generating additional
|
||||
// GC work. forEachP will guarantee that it is observed globally.
|
||||
work.strongFromWeak.block = true
|
||||
|
||||
// Flush all local buffers and collect flushedWork flags.
|
||||
gcMarkDoneFlushed = 0
|
||||
forEachP(waitReasonGCMarkTermination, func(pp *p) {
|
||||
@@ -872,6 +910,10 @@ top:
|
||||
goto top
|
||||
}
|
||||
|
||||
// For debugging/testing.
|
||||
for gcDebugMarkDone.spinAfterRaggedBarrier.Load() {
|
||||
}
|
||||
|
||||
// There was no global work, no local work, and no Ps
|
||||
// communicated work since we took markDoneSema. Therefore
|
||||
// there are no grey objects and no more objects can be
|
||||
@@ -910,6 +952,8 @@ top:
|
||||
}
|
||||
})
|
||||
if restart {
|
||||
gcDebugMarkDone.restartedDueTo27993 = true
|
||||
|
||||
getg().m.preemptoff = ""
|
||||
systemstack(func() {
|
||||
// Accumulate the time we were stopped before we had to start again.
|
||||
@@ -936,6 +980,11 @@ top:
|
||||
// start the world again.
|
||||
gcWakeAllAssists()
|
||||
|
||||
// Wake all blocked weak->strong conversions. These will run
|
||||
// when we start the world again.
|
||||
work.strongFromWeak.block = false
|
||||
gcWakeAllStrongFromWeak()
|
||||
|
||||
// Likewise, release the transition lock. Blocked
|
||||
// workers and assists will run when we start the
|
||||
// world again.
|
||||
|
||||
Reference in New Issue
Block a user