Skip to content

Commit edfc979

Browse files
committed
runtime: run safe-point function before entering _Psyscall
Currently, we run a P's safe-point function immediately after entering _Psyscall state. This is unsafe, since as soon as we put the P in _Psyscall, we no longer control the P and another M may claim it. We'll still run the safe-point function only once (because doing so races on an atomic), but the P may no longer be at a safe-point when we do so. In particular, this means that the use of forEachP to dispose all P's gcw caches is unsafe. A P may enter a syscall, run the safe-point function, and dispose the P's gcw cache concurrently with another M claiming the P and attempting to use its gcw cache. If this happens, we may empty the gcw's workbuf after putting it on work.{full,partial}, or add pointers to it after putting it in work.empty. This will cause an assertion failure when we later pop the workbuf from the list and its object count is inconsistent with the list we got it from. Fix this by running the safe-point function just before putting the P in _Psyscall. Related to #11640. This probably fixes this issue, but while I'm able to show that we can enter a bad safe-point state as a result of this, I can't reproduce that specific failure. Change-Id: I6989c8ca7ef2a4a941ae1931e9a0748cbbb59434 Reviewed-on: https://go-review.googlesource.com/12124 Run-TryBot: Austin Clements <[email protected]> Reviewed-by: Russ Cox <[email protected]>
1 parent 64e5333 commit edfc979

File tree

1 file changed

+5
-4
lines changed

1 file changed

+5
-4
lines changed

src/runtime/proc1.go

+5-4
Original file line numberDiff line numberDiff line change
@@ -1828,15 +1828,16 @@ func reentersyscall(pc, sp uintptr) {
18281828
save(pc, sp)
18291829
}
18301830

1831+
if _g_.m.p.ptr().runSafePointFn != 0 {
1832+
// runSafePointFn may stack split if run on this stack
1833+
systemstack(runSafePointFn)
1834+
}
1835+
18311836
_g_.m.syscalltick = _g_.m.p.ptr().syscalltick
18321837
_g_.sysblocktraced = true
18331838
_g_.m.mcache = nil
18341839
_g_.m.p.ptr().m = 0
18351840
atomicstore(&_g_.m.p.ptr().status, _Psyscall)
1836-
if _g_.m.p.ptr().runSafePointFn != 0 {
1837-
// runSafePointFn may stack split if run on this stack
1838-
systemstack(runSafePointFn)
1839-
}
18401841
if sched.gcwaiting != 0 {
18411842
systemstack(entersyscall_gcwait)
18421843
save(pc, sp)

0 commit comments

Comments
 (0)