systemstack(func() {
stw = stopTheWorldWithSema(stwGCSweepTerm)
})
+
+ // Accumulate fine-grained stopping time.
+ work.cpuStats.accumulateGCPauseTime(stw.stoppingCPUTime, 1)
+
// Finish sweep before we start concurrent scan.
systemstack(func() {
finishsweep_m()
// below. The important thing is that the wb remains active until
// all marking is complete. This includes writes made by the GC.
+ // Accumulate fine-grained stopping time.
+ work.cpuStats.accumulateGCPauseTime(stw.stoppingCPUTime, 1)
+
// There is sometimes work left over when we enter mark termination due
// to write barriers performed after the completion barrier above.
// Detect this and resume concurrent mark. This is obviously
if restart {
getg().m.preemptoff = ""
systemstack(func() {
+ // Accumulate the time we were stopped before we had to start again.
+ work.cpuStats.accumulateGCPauseTime(nanotime()-stw.finishedStopping, work.maxprocs)
+
+ // Start the world again.
now := startTheWorldWithSema(0, stw)
work.pauseNS += now - stw.startedStopping
})
reason stwReason
startedStopping int64
finishedStopping int64
+ stoppingCPUTime int64
}
// Temporary variable for stopTheWorld, when it can't write to the stack.
preemptall()
// stop current P
gp.m.p.ptr().status = _Pgcstop // Pgcstop is only diagnostic.
+ gp.m.p.ptr().gcStopTime = start
sched.stopwait--
// try to retake all P's in Psyscall status
trace = traceAcquire()
trace.ProcSteal(pp, false)
}
pp.syscalltick++
+ pp.gcStopTime = nanotime()
sched.stopwait--
}
}
break
}
pp.status = _Pgcstop
+ pp.gcStopTime = nanotime()
sched.stopwait--
}
wait := sched.stopwait > 0
sched.stwStoppingTimeOther.record(startTime)
}
- // sanity checks
+ // Double-check we actually stopped everything, and all the invariants hold.
+ // Also accumulate all the time spent by each P in _Pgcstop up to the point
+ // where everything was stopped. This will be accumulated into the total pause
+ // CPU time by the caller.
+ stoppingCPUTime := int64(0)
bad := ""
if sched.stopwait != 0 {
bad = "stopTheWorld: not stopped (stopwait != 0)"
if pp.status != _Pgcstop {
bad = "stopTheWorld: not stopped (status != _Pgcstop)"
}
+ if pp.gcStopTime == 0 && bad == "" {
+ bad = "stopTheWorld: broken CPU time accounting"
+ }
+ stoppingCPUTime += finish - pp.gcStopTime
+ pp.gcStopTime = 0
}
}
if freezing.Load() {
worldStopped()
- return worldStop{reason: reason, startedStopping: start, finishedStopping: finish}
+ return worldStop{
+ reason: reason,
+ startedStopping: start,
+ finishedStopping: finish,
+ stoppingCPUTime: stoppingCPUTime,
+ }
}
// reason is the same STW reason passed to stopTheWorld. start is the start
lock(&sched.lock)
if sched.gcwaiting.Load() {
pp.status = _Pgcstop
+ pp.gcStopTime = nanotime()
sched.stopwait--
if sched.stopwait == 0 {
notewakeup(&sched.stopnote)
pp := releasep()
lock(&sched.lock)
pp.status = _Pgcstop
+ pp.gcStopTime = nanotime()
sched.stopwait--
if sched.stopwait == 0 {
notewakeup(&sched.stopnote)
}
traceRelease(trace)
}
+ pp.gcStopTime = nanotime()
pp.syscalltick++
if sched.stopwait--; sched.stopwait == 0 {
notewakeup(&sched.stopnote)